Build new applications in the cloud - or use interoperable services that run on Microsoft infrastructure to extend and enhance your existing applications. You choose what's right for you.

Table of Contents

Lab 1 — Windows Azure Storage using Blob Service

 

In this lab, you will learn how to access Windows Azure Blob Service by using Windows Azure SDK for Java Developers.

 

Introduction

 

This lab will focus on Windows Azure Blob Service which offers storage for large data items.

 

Blobs consist of unstructured file-based data stored in an array of bytes; containers store sets of individual blobs up to 50GB in size in hierarchical groups, which emulate a directory structure. Only blob containers and their content are available for public access.

 

Windows Azure Blob service supports a massively scalable blob system, where hot blobs will be served from many servers to scale out and meet the traffic needs of your application. Furthermore, the system is highly available and durable. You can always access your data from anywhere at any time, and the data is replicated at least 3 times for durability. In addition, strong consistency is provided to ensure that the object is immediately accessible once it is added or updated; a subsequent read will immediately see the changes made from a previously committed write.

 

 

Task 0 — Prerequisites

 

Before doing this lab, if you not done so:

  1. Complete:           SDK Download
  2. Register:             Windows Azure Platform — Account Information.
  3. Get Blobs Lab:   Download
 Note:

Enter Windows Azure Account Information

To use download lab sample and its JUnit, you must modify these static variables with your Windows Azure Account information:

  • public static final String AZURE_ACCOUNT_NAME = "MyAccountName";
  • public static final String AZURE_ACCOUNT_KEY = "MyAccountKey";

 

Task 1 — Access Blob Storage Account

 

All access to Windows Azure Storage is done through a storage account. For a user to create a storage account, this is done via the Windows Azure portal web interface. The user will receive a 256-bit secret key once the account is created. This secret key is then used to authenticate user requests to the storage system.

 

The Blob service stores sets of binary data. The Blob service offers the following three resources: the storage account, containers, and blobs.

 

The REST API for the Blob service provides a way to work with blobs via HTTP operations.

 

Within your storage account, containers provide a way to organize sets of blobs within your storage account. Once you have access to Windows Azure Storage through your storage account, you now have:

 

The namespace is used to perform all access to Windows Azure Blob Service. The URI for a specific blob is structured as follows:

Blob Namespace
    http://<account>.blob.core.windows.net/<container>/<blobname>

 

The storage account name is specified as the first part of the hostname followed by the keyword "blob". This sends the request to the part of Windows Azure Storage that handles blob requests. The host name is followed by the container name, followed by "/", and then the blob name. Accounts and containers have naming restrictions (see the SDK document for details), for example, the container name cannot contain a "/".

Using SDK — Create Blob Storage Access

To use Blobs within Windows Azure Storage, you need a create a client that will act as a communication proxy to this service.

 

An instance of BlobStorageClient creates a Blob Storage Client.

 

To access this Host, you will need to replace "MyAccountName" and "MyAccountKey" with your Windows Azure Services account information.

 

Sample Code

BlobSample::createStorageAccess() performs the following:

  1. Creates a BlobStorageClient instance with:
    • Host Address — The Host that will service the Blob Storage Client using namespace http://blob.core.windows.net/
    • Azure Account Name — Used to build the URL that points to your storage.
    • Azure Account Key — Used to access your storage.
  2. method BlobStorageClient::setRetryPolicy() sets a Retry Policy to a specified time interval of 5 seconds.
 Note:

Retry Policies

A Storage Client can be assigned a retry policy. A retry policy specifies how the application will retry a request that has failed.

  • No retry
  • Retry at a specified interval
  • Retry at a randomized exponential interval, which may be configured within a minimum and maximum range.

Java — Creating Blob Storage Access
import java.net.URI;
import java.util.List;

import org.soyatec.windowsazure.blob.BlobStorageClient;
import org.soyatec.windowsazure.blob.internal.RetryPolicies;
import org.soyatec.windowsazure.error.StorageException;
import org.soyatec.windowsazure.internal.util.TimeSpan;

  /* * * * */

  protected static final String BLOB_HOST_NAME      = "http://blob.core.windows.net/";

  /*
   * Must register with Windows Azure in order to get your Account Name and Account Key.
   */
  protected static final String AZURE_ACCOUNT_NAME  = "YourAccountName";
  protected static final String AZURE_ACCOUNT_KEY   = "YourAccountKey";

  /**
   * Create client proxy to Blob Storage service.
   *
   * @param strAccountName
   * @param strAccountKey
   * @return BlobStorageClient instance.
   */
  public static BlobStorageClient createStorageAccess( String strAccountName,
                                                     String strAccountKey
                                                     )
  {
    /* * * * */

      objBlobStorage = BlobStorageClient.create(
                          URI.create( BlobSample.BLOB_HOST_NAME ),
                                      false,
                                      strAccountName,
                                      strAccountKey
                                      );

      /*  Set retry policy for a time interval of 5 seconds. */
      objBlobStorage.setRetryPolicy(RetryPolicies.retryN(1, TimeSpan.fromSeconds(5)));

    /* * * * */

    return objBlobStorage;

 

Sample Code

JUnit — Test Creating a Blob Storage client
  private BlobStorageClient m_objBlobStorage;

  /**
   * Sets up the test fixture.
   *
   * Called before every test case method.
   */
  protected void setUp()
  {
    m_objBlobStorage = BlobSample.getBlobStorage();
    BlobSample.emptyBlobStorage(m_objBlobStorage);
  }

  /**
   * Test that blob storage was created.
   */
  public void testValdidateSetUp()
  {
    assertNotNull(m_objBlobStorage);
    int count = BlobSample.countBlobContainers(m_objBlobStorage);
    assertEquals(0, count);
  }

 

Task 2 — Managing Blob Containers

 

Blob Container provides a grouping of a set of blobs. The container name is scoped by the account.

 

Containers are scoped by accounts. The storage system handles containers in a distributed manner, and there is no centralize resource bottleneck in terms of dealing with containers. The goal is to allow container operations to be on the high availability code paths of your application.

 

There can be a delay when recreating a recently deleted container, especially when there were a large number of blobs in that container. The system needs to reclaim the blobs in that container before the same container name can be created again. While the server is deleting all of the blobs, recreating the container will fail with an error indicating the container is being deleted.

 

When an application deletes a container or creates a brand new container, these commands are quickly committed on the server with acknowledgement back to the application, even though the delete can go on for awhile. Therefore, these can be on the high availability code paths for an application.

 

 

Create Blob Container

Create Container operation creates a new container under the specified account. If the container with the same name already exists, the operation fails.

 

The container resource includes metadata and properties for that container. It does not include a list of the blobs contained by the container.

 

A successful operation returns status code 201 (Created).

 Note:

Container Names

The URL to reference a container must be unique. Because every account name is unique, two accounts can have containers with the same name. However, within a given storage account, every container must have a unique name.

 

The container name must be a valid DNS name, conforming to the following naming rules:

  • Container names must start with a letter or number, and can contain only letters, numbers, and the dash (-) character.
  • Every dash (-) character must be immediately preceded and followed by a letter or number.
  • All letters in a container name must be lowercase.
  • Container names must be from 3 through 63 characters long.

 

Using SDK — Create Blob Container

With the Blob Storage Account access through an instance of BlobStorageClient, you can get a reference to a newly created IBlobContainer object by using method BlobStorageClient::getBlobContainer().

 

BlobStorageClient::createContainer() operation creates a new container under the specified account. If the container with the same name already exists, the operation fails.

 

Sample Code

BlobSample::getBlobContainer() performs the following:

  1. BlobStorageClient.createContainer () Tries to create a container by name.
  2. If the container does exist, then it throw StorageException.
  3. If creating the container succeeds, then it is returned.

 

Java — Get if Exists or Create Blob Container
  public static IBlobContainer getBlobContainer_wMetadata (
                                                BlobStorageClient objBlobStorage,
                                                String strBlobContainerName,
                                                NameValueCollection objMetadata
                                                )
    throws IllegalArgumentException
  {
      /* Create objBlobContainer by name */
      IBlobContainer objBlobContainer = objBlobStorage.createContainer(strBlobContainerName);
      if (null == objBlobContainer) {
        throw new NullPointerException("BlobContainer");
      }
        /* Set metadata to Blob Container */
      if (null != objMetadata) {
        objBlobContainer.setMetadata(objMetadata);
      }
      return objBlobContainer;
  }
 

 

Delete Blob Container

Delete Container operation marks the specified container for deletion. The container and any blobs contained within it are later deleted during garbage collection.

 

A successful operation returns status code 202 (Accepted).

 

When a container is deleted, a container with the same name cannot be created for at least 30 seconds; the container may not be available for more than 30 seconds if the service is still processing the request. While the container is being deleted, attempts to create a container of the same name will fail with status code 409 (Conflict), with the service returning additional error information indicating that the container is being deleted. All other operations, including operations on any blobs under the container, will fail with status code 404 (Not Found) while the container is being deleted.

 

Using SDK — Delete Blob Container from Storage

  1. IBlobContainer::isContainerExist() checks if container exists in Blob Storage.
  2. BlobStorageClient::deleteContainer() delete container from Blob Storage.

 

Sample Code

BlobSample::deleteBlobContainer() performs the following:

  1. Checks if selected container exists in Blob Storage.
  2. If it exists, then deletes container from Blob Storage.
  3. If requested to confirm that a container is deleted from Blob Storage:
    1. Waits 40 seconds.
    2. Checks if selected container no longer exists in Blob Storage.

 

Java — Delete Blob Container
  public static boolean deleteBlobContainer ( BlobStorageClient objBlobStorage,
                                              IBlobContainer objBlobContainer,
                                              boolean fConfirmDelete
                                            )
    throws Exception
  {
    /* * * * */
    String containerName = objIBlobContainer.getContainerName();
    if(objBlobContainer.isContainerExist()) {
      if(!objBlobStorage.deleteContainer(containerName)) {
        throw new Exception("Unexpected");
      }
    }

    if (fConfirmDelete) {
      /* The amount of delay for deleting container. */
      Thread.sleep(40000);
      fStatus = !objBlobContainer.isContainerExist();
    } else {
      fStatus = true;
    }

    return fStatus;
  }

 

Sample Code

Java — Delete Blob Container by Name
  public static boolean deleteBlobContainer ( BlobStorageClient objBlobStorage,
                                              String strContainerName,
                                              boolean fConfirmDelete
                                            )
  throws Exception
  {
    /* * * * */

    IBlobContainer objBlobContainer = objBlobStorage.getBlobContainer(strContainerName);

    return BlobSample.deleteBlobContainer(objBlobStorage, objBlobContainer, fConfirmDelete);
  }

 

Sample Code— Delete All Blob Containers from Storage

BlobSample::deleteBlobContainersAll() performs the following:

  1. BlobStorageClient::listBlobContainers() returns all containers in Blob Storage.
  2. BlobStorageClient::deleteContainer() deletes a container and expect confirmation of deletion.

 

Java — Empty Blob Storage of Containers
  public static boolean deleteBlobContainersAll( BlobStorageClient objBlobStorage,
                                          boolean fConfirmDelete
                                          )
  {
  /* * * * */

      List<IBlobContainer> listBlobContainers = objBlobStorage.listBlobContainers();

      if (null != listBlobContainers) {
        for (IBlobContainer objBlobContainer : listBlobContainers)
        {
          String strContainerName = objBlobContainer.getContainerName();

          if (!BlobSample.deleteBlobContainer(objBlobStorage, objBlobContainer, fConfirmDelete)) {
            throw new Exception("Failed to delete " + strContainerName);
          }
        }
      }

  /* * * * */

 

 

Task 3 — Enumerating Blob Containers

 

The Blob service API includes operations for enumerating the containers within an account.

 

Using SDK — List Blob Containers

 

BlobStorageClient::listBlobContainers() operation returns a list of the containers under the specified account.

 

Sample Code

BlobSample::listBlobContainers() uses BlobStorageClient to printout a listing a containers.

 

Java — List Blob Containers
  public static void listBlobContainers( BlobStorage objBlobStorage )
  {
  /* * * * */

      List<IBlobContainer> listBlobContainers = objBlobStorage.listBlobContainers();

      System.out.println("------------------");
      if (null != listBlobContainers && !listBlobContainers.isEmpty()) {
        System.out.printf("List of Blob Containers in Account %s\n",
                  objBlobStorage.getAccountName()
                  );

          for ( IBlobContainer objBlobContainer : listBlobContainers ) {
            System.out.println(objBlobContainer.getContainerName());
          }
      }
      else {
        System.out.printf("No Blob Containers in Account %s\n",
          objBlobStorage.getAccountName()
          );
      }
      System.out.println("------------------");

  /* * * * */
  }

 

Sample Code — Count Blob Containers

BlobSample::countBlobContainers() uses BlobStorage::listBlobContainers() to get the size of the list to determine count.

 

Java — List Blob Containers
  /**
   * Number of Blob containers in storage account.
   *
   * @param objBlobStorage BlobStorageClient
   * @return int Count
   */
  public static int countBlobContainers( BlobStorageClient objBlobStorage )
  {

  /* * * * */

    try {
      List<IBlobContainer> listBlobContainers = objBlobStorage.listBlobContainers();

      if (null != listBlobContainers) {
        count = listBlobContainers.size();
      }

  /* * * * */

    return count;
  }

 

 

Task 4 — Managing Container Metadata

 

Containers support custom metadata, represented as HTTP headers. Metadata headers can be set on a request that creates a new container, or on a request that explicitly creates a property on an existing container.

 

Metadata is a collection of one or more user-defined name/value pairs.

 

Names are case-insensitive. If two or more headers with the same name are submitted for a resource, the headers will be combined into a single header with a comma delimiting each value.

 

The total size of the metadata, including both the name and value together, may not exceed 8 KB in size.

 

Metadata on a container resource can be retrieved or set directly, without returning or altering the content of the resource.

 

 Note:

Metadata values can only be read or written in full; partial updates are not supported. Setting metadata on a resource overwrites any existing metadata values for that resource.

 

Using SDK — Set Container Metadata

NameValueCollection is used to build the user-defined metadata with one or more name-value pairs.

 

IBlobContainer::setMetadata() sets user-defined metadata for the specified container with a populated NameValueCollection.

 

Using SDK — Get Container Metadata

IBlobContainer::getProperties() returns a ContainerProperties.

 

IContainerProperties holds the container's metadata.

 

IContainerProperties::getMetadata() returns a NameValueCollection which a collection of the container's metadata.

 

Sample Code

BlobSample::getBlobContainer_wMetadata() shows how to set and get a container's metadata.

 

Java — Set and Get Container Metadata
import org.soyatec.windowsazure.util.NameValueCollection;

  /* * * * */

  public static IBlobContainer getBlobContainer_wMetadata (
                                                BlobStorageClient objBlobStorage,
                                                String strBlobContainerName,
                                                NameValueCollection objMetadata
                                                )
    throws IllegalArgumentException
  {

      /* * * * */

      /* Fetch objBlobContainer by name */
      objBlobContainer = objBlobStorage.getBlobContainer(strBlobContainerName);
      if (null == objBlobContainer) {
        throw new NullPointerException("BlobContainer");
      }

      /* Check if it exist */
      if (!objBlobContainer.isContainerExist()) {
        /* If objBlobContainer does not exist, create it */
        objBlobContainer = objBlobStorage.createContainer(strBlobContainerName);
        /* Set metadata to Blob Container */
        if (null != objMetadata) {
          objBlobContainer.setMetadata(objMetadata);
        }
      } else {
        if (null != objMetadata) {
          IContainerProperties objContainerProperties = objBlobContainer.getProperties();
          objMetadata = objContainerProperties.getMetadata();
        }
      }

 

JUnit shows how BlobSample is called for setting and getting BlobContainer metadata within NameValueCollection.

 

JUnit — Test Set and Get Container Metadata
  /**
   * Test Container with metadata.
   */
  public void testContainer_wMetadata()
  {
    try {

      /* * * * */

      NameValueCollection objMetadataContainerPre = new NameValueCollection();
      IBlobContainer objBlobContainerPre
          = BlobSample.getBlobContainer_wMetadata(
              m_objBlobStorage,
              strContainerName,
              objMetadataContainerPre /* No metadata */
              );

      NameValueCollection objMetadataPut = new NameValueCollection();
      objMetadataPut.put("createdBy", METADATA_CREATED_BY);
      fSuccess = BlobSample.setBlobContainer_wMetadata( objBlobContainerPre,
                                                        objMetadataPut);
      assertTrue(fSuccess);

      NameValueCollection objMetadataContainerPost = new NameValueCollection();
      IBlobContainer objBlobContainerPost
          = BlobSample.getBlobContainer_wMetadata(
              m_objBlobStorage,
              strContainerName,
              objMetadataContainerPost
              );
      assertNotNull(objBlobContainerPost);

      String strCreatedBy = (String) objMetadataContainerPost.getSingleValue("createdBy");
      assertTrue(strCreatedBy.equals(METADATA_CREATED_BY));

 

 

Task 5 — Managing Blobs with Binary Data

 

The Blob service is for storing unstructured data.

 

Blobs are written to the Blob service by using a PUT operation defined by the REST API. Blobs less than or equal to 64 MB in size can be uploaded with a single PUT operation. Blobs larger than 64 MB must be uploaded as a set of blocks, each of which is less than or equal to 4 MB in size. A set of successfully uploaded blocks can be assembled in a specified order into a single contiguous blob. One block can be specified multiple times in the list of blocks that will comprise a blob. The maximum blob size currently supported is 50 GB.

 

Blobs support conditional update operations that may be useful for concurrency control and efficient uploading.

 

Blobs can be read by using a GET operation defined by the REST API. A client may read the entire blob, or an arbitrary range of bytes.

 

 Note:

Blob Names

The URL to reference a blob must be unique. Every blob within a given container must also have a unique name.

 

The blob name must conform to the following naming rules:

  • 1,024 Characters Max
  • Any combination of characters, but reserved URL characters must be properly escaped.
  • Specify a delimiter within a blob name to create a virtual hierarchy though blob storage is flat and not a hierarchical.

Avoid blob names that end with a dot (.), a forward slash (/), or a sequence or combination of the two. The URL that identifies a blob is constructed with the .NET URL class, which compacts a URL that ends with these sequences. A blob with a name that contains such a sequence may not be accessible via its original name.

 

Using SDK — Create Blob with Binary Data

IBlobContainer::createBlockBlob() method to put a blob to the specified container.

 

Parameters:

 

BlobMemoryStream is used to write binary data into blob content.

 

BlobMemoryStream class creates streams that have memory as a backing store instead of a disk or a network connection, it encapsulates data stored as an unsigned byte array that is initialized upon creation of a BlobMemoryStream object, or the array can be created as empty. The encapsulated data is directly accessible in memory. Memory streams can reduce the need for temporary buffers and files in an application.

 

Sample Code

BlobSample::putBlob_wBinaryData_wMetadata() shows how to put a BlobMemoryStream into a blob that will be put into a specified container.

 

Java — Put Blob with Binary Data into a Container
import org.soyatec.windowsazure.blob.IBlobProperties; 
import org.soyatec.windowsazure.blob.IBlobContents;
import org.soyatec.windowsazure.blob.io.BlobMemoryStream;
import org.soyatec.windowsazure.internal.util.NameValueCollection;

  /* * * * */

  public static boolean putBlob_wBinaryData_wMetadata(
                                            IBlobContainer objBlobContainer,
                                            String strBlobName,
                                            byte[] binaryBlobData,
                                            NameValueCollection objMetadata,
                                            boolean fOverwrite
                                            )
  throws Exception
  {

      /* * * * */

      /* New Blob Properties */
      IBlobProperties objBlobProperties = new BlobProperties(strBlobName);
      objBlobProperties.setContentType(CONTENT_TYPE_BINARY);

      /* Set Metadata */
      if (null != objMetadata && (objMetadata instanceof NameValueCollection)) {
        objBlobProperties.setMetadata(objMetadata);
      }

      /* Set Blob Contents */
      BlobMemoryStream objStream      = new BlobMemoryStream(binaryBlobData);
      IBlobContents objBlobContents   = new BlobContents(objStream);

      if (!objBlobContainer.createBlockBlob(   objBlobProperties,
                                          objBlobContents)) {
        throw new Exception("Failed to create blob");
      }

 

Using SDK — Get Blob with Binary Data

IBlob::getContents() method downloads the blob if it exists.

 

Parameters:

 

Sample Code

BlobSample::getBlob_wBinaryData_wMetadata() shows you how to get a blob with binary data.

 

Java — Get Blob with Binary Data from a Container
  public static byte[] getBlob_wBinaryData_wMetadata(
                                         IBlobContainer objBlobContainer,
                                          String strBlobName,
                                          NameValueCollection objMetadata
                                          )
    throws Exception
  {

      /* * * * */

      BlobMemoryStream objStream   = new BlobMemoryStream();
      IBlockBlob blob = objBlobContainer.getBlockBlobReference(strBlobName);
      
      IBlobProperties objBlobProperties = blob.getProperties( );

      /* * * * */
      blob.getContents(objStream);
      bytesResult = objStream.getBytes();

 

JUnit shows how BlobSample uses IBlob to set and get blob binary data using BlobMemoryStream.

 

By default the access mode of a container is private. In JUnit, at /* Validate URL access */, URL access to the blob is tried when container is in private access mode and then in public access mode.

 

JUnit — Test Put and Get Blob with Binary Data into a Container
  /**
   * Test Put and Get of Blob binary data into a Container
   */
  public void testBlob_wBinaryData()

      /* * * * */

      /*
       * Define the binary data to be held within a blob.
       * To create binary data, transform a String into a byte array.
       */
      String strTest1 = "a2Xy337u7bg9sbbxNcAU3SyQt8TExeQI";
      String strBlobName = "RandomString";
      int intStrLength = strTest1.length();
      byte[] binaryData = strTest1.getBytes();
      byte[] binaryDataResult = null;

      /* False test, Blob should not exist */
      binaryDataResult
                  = BlobSample.getBlob_wBinaryData_wMetadata(
                                                  objBlobContainer,
                                                  strBlobName,
                                                  null /* Get not metadata */
                                                  );
      assertNull(binaryDataResult);

      /* Create Blob "RandomString" with binary data */
      fSuccess = BlobSample.putBlob_wBinaryData_wMetadata(
                                                objBlobContainer,
                                                strBlobName,
                                                binaryData,
                                                null, /* No metadata */
                                                false
                                                );
      assertTrue(fSuccess);

      int count = BlobSample.countBlobs(objBlobContainer, null);
      assertEquals(1, count);

      /* Get the binary data from Blob "RandomString" */
      NameValueCollection objMetadataGet = new NameValueCollection();
      binaryDataResult
                  = BlobSample.getBlob_wBinaryData_wMetadata (
                                                  objBlobContainer,
                                                  strBlobName,
                                                  objMetadataGet
                                                  );
      assertNotNull(binaryDataResult);


 

 

Task 6 — Managing Blobs with File binary

 

Using SDK — Create Blob with File binary

IBlobContainer::createBlockBlob() method to put a blob to the specified container.

 

BlobFileStream class is used to wrap the binary contents of a file, which will then be placed into a blob that will be placed into a container.

 

Sample Code

BlobSample::putBlob_wFile_wMetadata() shows how to use BlobContainer::createBlockBlob() to send a file to a blob assisted by BlobFileStream.

 

Java — Put Blob with File binary into a Container
import org.soyatec.windowsazure.blob.IBlobProperties; 
import org.soyatec.windowsazure.blob.IBlobContents;
import org.soyatec.windowsazure.blob.io.BlobFileStream;

  /* * * * */

  public static boolean putBlob_wFile_wMetadata (
                                    BlobContainer objBlobContainer,
                                    String strBlobName,
                                    String strFilePath,
                                    NameValueCollection objMetadata,
                                    boolean fOverwrite
                                    )
  throws Exception
  {
      /* * * * */

      /* Set Blob properties */
      IBlobProperties objBlobProperties = new BlobProperties(strBlobName);
      objBlobProperties.setContentType(CONTENT_TYPE_FILE);

      /* Set Metadata */
      if (null != objMetadata && (objMetadata instanceof NameValueCollection)) {
        objBlobProperties.setMetadata(objMetadata);
      }

      /* Set Blob contents */
      BlobFileStream objStream       = new BlobFileStream(strFilePath);
      IBlobContents objBlobContents  = new BlobContents(objStream);

      if (!objBlobContainer.createBlockBlob(objBlobProperties, objBlobContents)) {
        throw new Exception("Failed to create blob");
      }

      /* * * * */

 

Using SDK — Get Blob with File binary

IBlob::getContents() method downloads the blob if it exists.

 

Parameters:

 

Sample Code

BlobSample::getBlob_wFile_wMetadata() shows you how to get a blob with file binary.

 

Java — Get Blob with File binary from a Container
  public static boolean getBlob_wFile_wMetadata (
                                      IBlobContainer objBlobContainer,
                                      String strBlobName,
                                      String strFilePath,
                                      NameValueCollection objMetadata,
                                      boolean fOverwrite
                                      )
    throws Exception
  {
      /* * * * */

      BlobFileStream objStream   = new BlobFileStream(strFilePath);
      
     
      IBlob blob = objBlobContainer.getBlockBlobReference( strBlobName);
      
      IBlobContents objBlobContents = blob.getContents(objStream);
      /* * * * */

 

Sample Code

JUnit shows how BlobSample uses BlobContainer to set and get blob binary data using FileStream.

 

By default the access mode of a container is private. In JUnit, at /* Validate URL access */, URL access to the blob is tried when container is in private access mode and then in public access mode.

 

When access is public, then the blob image would be accessible through this URL: http://YOUR_ACCOUNT.blob.core.windows.net/testcontainer/WindowsAzure.jpg

 

JUnit — Test Put and Get a Blob with File binary
  /**
   * Test Put and Get a Blob with File binary within a Container
   */
  public void testBlob_wFile()
  {
      /* * * * */

      /*
       * Put File "WindowsAzure.jpg" binary into a Blob,
       * Label Blob with name "WindowsAzureImage",
       * then put Blob "WindowsAzure.jpg" into strContainerName Container.
       */
      fSuccess = BlobSample.putBlob_wFile_wMetadata(
                                          objBlobContainer,
                                          strBlobName,
                                          strFilePath,
                                          null, /* No metadata */
                                          true
                                          );
      assertTrue(fSuccess);

      int count = BlobSample.countBlobs(objBlobContainer, null);
      assertEquals(1, count);

      /*
       * Provide location to place retrieved File at "WindowsAzure2.jpg",
       * Get Blob with name "WindowsAzureImage" from strContainerName Container,
       * then copy retrieved Blob's File "WindowsAzure.jpg" binary into "WindowsAzure2.jpg".
       */
      NameValueCollection objMetadataGet = new NameValueCollection();
      fSuccess = BlobSample.getBlob_wFile_wMetadata(  objBlobContainer,
                                          strBlobName,
                                          "WindowsAzure2.jpg",
                                          objMetadataGet,
                                          true /* Overwrite if exists */
                                          );
      assertTrue(fSuccess);
      assertTrue(objMetadataGet.isEmpty());

 

 

Task 7 — Managing Blob Metadata

 

Using SDK — Set Blob Metadata

IBlobProperties class is used as a wrapper to hold Blob metadata.

 

NameValueCollection is used to build the user-defined Blob metadata with one or more name-value pairs.

 

IBlobProperties::setMetadata() sets user-defined metadata for the specified blob with a populated NameValueCollection.

 

Java — Set Blob Metadata
      /* Set Blob properties */
      IBlobProperties objBlobProperties = new BlobProperties(strBlobName);
      objBlobProperties.setContentType(CONTENT_TYPE_FILE);

      /* Set Metadata */
      if (null != objMetadata && (objMetadata instanceof NameValueCollection)) {
        objBlobProperties.setMetadata(objMetadata);
        blob.setProperties(objBlobProperties);
      }

 

Using SDK — Get Blob Metadata

IBlobProperties::getMetadata() gets user-defined metadata for the specified blob with a populated NameValueCollection.

 

Java — Get Blob Metadata
      IBlobProperties objBlobProperties = blob.getProperties( );

      /* Get Blob metadata */
      if ( null != objBlobProperties ) {
        objMetadata = objBlobProperties.getMetadata();
      }

 

 

Task 8 — Enumerating Blobs

 

The Blob service API includes operations for enumerating the blobs within a container.

 

Using the REST API for the Blob service, developers can create a hierarchical namespace similar to a file system.

 

For example, the following are all valid and unique blob names:

 

Blob names may encode a hierarchy by using a configurable path separator. For example, the blob names MyGroup/MyBlob1 and MyGroup/MyBlob2 imply a virtual level of organization for blobs. The enumeration operation for blobs supports traversing the virtual hierarchy in a manner similar to that of a file system, so that you can return a set of blobs that are organized beneath a group. For example, you can enumerate all blobs organized under MyGroup/.

 

Using SDK — List Blobs

IBlobContainer::listBlobs(java.lang.String prefix, boolean combineCommonPrefixes) operation enumerates the list of blobs with the given prefix under the specified container.

 

IBlobContainer::listBlobs(java.lang.String prefix, boolean combineCommonPrefixes, int maxResults) operation specifies the maximum number of blobs to return per call with the given prefix under the specified container.

 

Sample Code

BlobSample::listBlobsAll() lists all Blobs in a Container because it set prefix to empty string "" and combineCommonPrefixes to false.

  ------------------
  List of Blobs in Container testcontainer1
  Random_1/blob_5HECN.txt
  Random_1/blob_BTXX4.txt
  Random_1/blob_fKTWw.txt
  Random_1/blob_qHntG.txt
  Random_1/blob_spigl.txt
  Random_2/blob_MFh9N.txt
  Random_2/blob_RMHZl.txt
  Random_2/blob_Tzut8.txt
  Random_2/blob_oW3VA.txt
  Random_2/blob_wRukc.txt
  ------------------

 

Java — List All Blobs in a Container
  public static boolean listBlobsAll (  IBlobContainer objBlobContainer,
                                        Collection<IBlobProperties> listBlobProperties,
                                        boolean fPrintList
                                        )
  {
    return BlobSample.listBlobs(objBlobContainer,
                                null, /* No prefix */
                                listBlobProperties,
                                fPrintList
                                );
  }

 

Sample Code

BlobSample::listBlobs() lists all Blobs in a Container that begins with a prefix.

 

------------------
List of Blobs with prefix 'Random_1/' in Container 'testcontainer1'
Random_1/blob5HECN.txt
Random_1/blobBTXX4.txt
Random_1/blobFKTWW.txt
Random_1/blobQHNTG.txt
Random_1/blobSPIGL.txt
------------------

------------------
List of Blobs with prefix 'Random_2/' in Container 'testcontainer1'
Random_2/blobMFH9N.txt
Random_2/blobOW3VA.txt
Random_2/blobRMHZL.txt
Random_2/blobTZUT8.txt
Random_2/blobWRUKC.txt
------------------

 

Java — List Blobs in a Container
  public static boolean listBlobs (   IBlobContainer objBlobContainer,
                                      String strPrefix,
                                      Collection<IBlobProperties> listBlobProperties,
                                      boolean fPrintList
      )
  {
    boolean fSuccess = false;

    if ( null == strPrefix ) {
      strPrefix = "";
    }

    try {
      Iterator<IBlobProperties> listBlobPropertiesTmp = null;

      listBlobPropertiesTmp = objBlobContainer.listBlobs( strPrefix, false);

      if (fPrintList) {
        System.out.println("------------------");
        if (null != listBlobPropertiesTmp && listBlobPropertiesTmp.hasNext()) {
          if (strPrefix.isEmpty()) {
            System.out.printf(  "List of Blobs in Container '%s'\n",
                      objBlobContainer.getContainerName()
                      );
          } else {
            System.out.printf(  "List of Blobs with prefix '%s' in Container '%s'\n",
                strPrefix,
                objBlobContainer.getContainerName()
                );
          }

          while (listBlobPropertiesTmp.hasNext()) {
          
             IBlobProperties objBlobProperties = listBlobPropertiesTmp.next();          
             System.out.println(objBlobProperties.getName());
             if ( null != listBlobProperties) {              
                listBlobProperties.add(objBlobProperties);
             }
          }
        } else {
          System.out.printf(  "No Blobs in Container %s\n",
            objBlobContainer.getContainerName() );
        }
        System.out.println("------------------");
      }

      fSuccess = true;
    } catch ( StorageException e ) {
      e.printStackTrace();
    } catch ( Exception e ) {
      e.printStackTrace();
    }

    return fSuccess;
  }

 

Task 9 — Copying Blobs

 

The Blob service API includes operations to copy a blob from a source blob to a destination blob within the same storage account. This copies the whole blob, including the blob metadata, properties, and committed block list.

 

This enables applications to:

 

Using SDK — Copy Blob

IBlobContainer::copyBlob(String destContainer, String destBlobName, String sourceBlobName) method is to copy a blob to a destination within the storage account.

 

When the source blob and destination blob are the same, BlobContainer::copyBlob() removes any uncommitted blocks.

 

IBlobContainer::copyBlob(String destContainer, String destBlobName, String sourceBlobName, NameValueCollection metadata, IBlobConstraints constraints) method can specify one or more new metadata values for the destination blob.

 

If metadata is specified in this case, the existing metadata is overwritten with the new metadata.

 

Sample Code

BlobSample::copyBlob() demonstartes using copy operation.

 

Java — Copy Blob from Source to Destination Container
  public static boolean copyBlob( BlobStorageClient objBlobStorage,
                                  String strContainerSrc,
                                  String strContainerDest,
                                  String strBlobNameSrc,
                                  String strBlobNameDest,
                                  boolean fOverwriteDest
                                  )
  {
    boolean fSuccess = false;

    try {
      /* Validate Source container exists */
      IBlobContainer objBlobContainerSrc
            = objBlobStorage.getBlobContainer(strContainerSrc);
      if (null == objBlobContainerSrc || !objBlobContainerSrc.doesContainerExist()) {
        throw new Exception(String.format(  "Source Container '%s' does not exist",
                                            strContainerSrc));
      }

      /* Validate Source blob exists */
      if ( !objBlobContainerSrc.isBlobExist(strBlobNameSrc) ) {
        throw new Exception(String.format(  "Source Blob '%s' does not exist",
                                            strBlobNameSrc));
      }

      /* Validate Destination container exists */
      IBlobContainer objBlobContainerDest
            = objBlobStorage.getBlobContainer(strContainerDest);
      if (null == objBlobContainerDest || !objBlobContainerDest.doesContainerExist()) {
        throw new Exception(String.format(  "Destination Container '%s' does not exist",
                                            strContainerSrc));
      }

      /* Validate if Destination blob exists and do not overwrite */
      if ( objBlobContainerDest.isBlobExist(strBlobNameDest) && !fOverwriteDest ) {
        throw new Exception(  String.format("Destination Blob '%s' does exist and do not overwrite.",
                                            strBlobNameSrc));
      }

      fSuccess = objBlobContainerSrc.copyBlob( strContainerDest,
                                              strBlobNameDest,
                                              strBlobNameSrc );
    } catch ( StorageException e ) {
      e.printStackTrace();
    } catch ( Exception e ) {
      e.printStackTrace();
    }

    return fSuccess;
  }

 

Sample Code

JUnit shows how BlobSample uses BlobContainer to copy a blob.

 

JUnit — Copy Blob from Source to Destination Container
  /*
   * Test Copy Blob.
   */
  public void testCopyBlob()
  {
   try {
     boolean fSuccess = false;
     String strContainerSrc = "testcontainerSrc";
     String strContainerDest = "testcontainerDest";
     String strBlobNameSrc = "testblobSrc";
     String strBlobNameDest = "testblobDest";

      /* * * * */

     /* Copy source blob to destination blob */
     fSuccess = BlobSample.copyBlob(  m_objBlobStorage,
                                       strContainerSrc,
                                       strContainerDest,
                                       strBlobNameSrc,
                                       strBlobNameDest,
                                       true
                                       );
     assertTrue(fSuccess);

     /* Get destination blob */
     byte[] binaryDataDest
       = BlobSample.getBlobBinaryData( objBlobContainerDest,
                                       strBlobNameDest
                                       );
     assertNotNull(binaryDataDest);

      /* * * * */

 

 

Task 10 — Managing Container Access Control

 

When creating a container, by default it is in private access mode. In other words, it is only accessible by the account owner and not available to anonymous users.

 

When a container is changed to public access mode, then the contents (blobs) of the container are available to anonymous users.

 

Using SDK — Set Container Access Control

IBlobContainer::setAccessControl() sets the access control list (ACL) for the specified container. The ACL indicates whether blobs in a container may be accessed publicly.

 

Enum IContainerAccessControl provides values Public and Private for setting the ACL.

 

Sample Code

BlobSample::setBlobContainerACL() provides the option on setting a container's access to Public or Private.

 

Java — Setting Access Control to a Container
import org.soyatec.windowsazure.blob.IContainerAccessControl;

  /* * * * */

  public static boolean setBlobContainer_wACL ( IBlobContainer objBlobContainer,
                                                boolean fPublicAccess
                                              )
  throws IllegalArgumentException
  {
    boolean fSuccess = false;
    if ( null == objBlobContainer || !objBlobContainer.isContainerExist() ) {
      throw new IllegalArgumentException("BlobContainer parameter not defined!");
    }

    try {
      IContainerAccessControl enumAccess
            = fPublicAccess   ? IContainerAccessControl.Public
                              : IContainerAccessControl.Private;

      objBlobContainer.setAccessControl(enumAccess);
      fSuccess = true;
    } catch ( StorageException e ) {
      e.printStackTrace();
    } catch ( Exception e ) {
      e.printStackTrace();
    }

    return fSuccess;
  }

 

Summary

 

In this lab, you have learned how to...

 

 

Good job!! You are done with this Lab.