Gaurav Mantri's Personal Blog.

Consuming Windows Azure Service Management API In Java

I have written some blog posts about consuming Windows Azure Service Management API using C#. I have been quite active on StackOverflow trying to answer some questions about Windows Azure. Recently I observed a number of questions there asking for consuming this API through Java. Also somebody approached me asking for something like this. This blog post is a result of that. In this post, I will talk about how one can consume this API using Java.

Its been ages that I have worked with Java so things I describe below may sound trivial to experienced Java developers so please bear with me Smile. Also if there’re better ways to do things, please let me know as most of the code you will see below would be the result of massive Internet searches Smile.

About Windows Azure Service Management API

Let’s take a moment to talk briefly about what this API is and some other fundamental things about it and then we’ll get into the code.

What?

Windows Azure Service Management API is a REST based API for managing Windows Azure resources. Using this API, you can manage your cloud services, storage accounts, virtual machines, virtual networks and lot more. Essentially the things you could do on Windows Azure Portal can be done through this API. In fact, Windows Azure Portal is built on top of this API. You can learn more about this here: http://msdn.microsoft.com/en-us/library/windowsazure/ee460799.aspx.

How it Works?

To use this API, you would need 2 things:

  1. Subscription Id: This is a GUID which uniquely identifies your subscription. You can get this information through portal.
  2. Management Certificate: A management certificate is required to authenticate your API calls. This management certificate must be associated with your subscription which you can do by upload the certificate in the portal. You could either create a management certificate on your own and associate it with your subscription (this is covered in details in this post) or you could ask Windows Azure platform to create a management certificate for you and associate it with your subscription. This is done through a process called “Download Publish Profile File”. I have written a blog post about it some days back which you can read here: http://gauravmantri.com/2012/09/14/about-windows-azure-publish-settings-file-and-how-to-create-your-own-publish-settings-file/.

Since the API is a REST based API, the endpoints are accessible over HTTP. In your code, you create an endpoint specific to a particular kind of operation you want to perform. Then you create an HTTP request for that endpoint. To authenticate the request, you attach the management certificate along with that request. You can learn more about the authentication here: http://msdn.microsoft.com/en-us/library/windowsazure/ee460782.aspx.

Now that we know a bit about the API, let’s look at how we can consume this API using Java.

Using Publish Profile File

I will not go into details about consuming this API using the publish profile file as it is covered extremely well by Andy Cross and Richard Conway in their Elastacloud blog post: http://blog.elastacloud.com/2012/09/29/a-windows-azure-service-management-client-in-java/. If this is something you’re looking for, stop reading this post and head over to their website otherwise read on Smile.

Using Management Certificate

Rest of this post will cover how you could consume this API by creating your own management certificate. There are some things you would need to do first.

Step 1: Create a Keystore

Coming from .Net world, I was used to find certificate in certificate store and obviously I tried to do the same in Java as well Smile. Turns out, I have to create something called a Keystore. To create a Keystore, you would use a tool called (guess what Smile) Keytool. Here’s the command I used to create a Keystore:

keytool -genkeypair -alias mydomain -keyalg RSA -keystore WindowsAzureKeyStore.jks 
-keysize 2048 -storepass "test123";

image

What we’ve done is created a Keystore called “WindowsAzureKeyStore.jks” and set the password to access this as “test123”. You should see a file called “WindowsAzureKeyStore.jks” in “C:\Program Files\Java\jre7\bin” folder.

image

Step 2: Export Management Certificate

Next we’ll export a certificate from this Keystore we just created. To do so, again I will use Keytool. Here’s the command I used:

keytool -v -export -file D:\WindowsAzureSMAPI.cer -keystore WindowsAzureKeyStore.jks 
-alias mydomain

image

Once this operation completes, I will get a “WindowsAzureSMAPI.cer” file in “D:\” of my computer.

image

Step 3: Upload Certificate

Next step is to upload this certificate to the Windows Azure Portal. To do so, login into Windows Azure Portal at https://manage.windowsazure.com and click on “SETTINGS” tab and then go to “MANAGEMENT CERTIFICATES” tab and upload this “WindowsAzureSMAPI.cer” file there.

image

The Code

Now we’re ready to code Smile.

Step 1: Get Keystore

Since we need the management certificate to authenticate the request and the certificate is in the Keystore, first we will get it. To open a Keystore, we would need the full path of the Keystore we just created and it’s password. Here’s the code to do so:

	private static KeyStore getKeyStore(String keyStoreName, String password) throws IOException
	{
		KeyStore ks = null;
		FileInputStream fis = null;
		try {
			ks = KeyStore.getInstance("JKS");
			char[] passwordArray = password.toCharArray();
			fis = new java.io.FileInputStream(keyStoreName);
			ks.load(fis, passwordArray);
			fis.close();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			if (fis != null) {
				fis.close();
			}
		}
		return ks;
	}

Step 2: Get SSLSocketFactory

Here’s the code to get SSLSocketFactory:

	
	private static SSLSocketFactory getSSLSocketFactory(String keyStoreName, String password) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException, IOException {
		KeyStore ks = getKeyStore(keyStoreName, password);
		KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
		keyManagerFactory.init(ks, password.toCharArray());

		  SSLContext context = SSLContext.getInstance("TLS");
		  context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());

		  return context.getSocketFactory();
	}

Step 3: Execute HTTP Requests

Once we have this, all we have to do is execute HTTP requests.

Step 3.1: Create URL

Just create a URL based on the operation you want to perform. For example, assuming your subscription id is “fd9a283a-3a98-b17e-a2b8-763cf6e9ba18” and you want to perform “List Locations” operation, your URL would be: https://management.core.windows.net/fd9a283a-3a98-b17e-a2b8-763cf6e9ba18/locations

Step 3.2: Create HttpsURLConnection object

Using this URL, create an instance of HttpsUrlConnection object and set SSLSocketFactory.

		SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
		HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
		con.setSSLSocketFactory(sslFactory);

Step 3.3: Provide other necessary information

Specify other necessary information like required request method, request headers, content type etc. and execute the request. For example, if you want to perform “List Locations” operation, you would need to perform a “Get” request. The code would look something like this:

		con.setRequestMethod("GET");
		con.addRequestProperty("x-ms-version", "2012-03-01");
		InputStream responseStream = (InputStream) con.getContent();
		String response = getStringFromInputStream(responseStream);
		responseStream.close();
		return response;

That’s pretty much to it!

Helper Functions

As I was working on this, I abstracted some functionality and created some helper functions for them. Here they are for your convenience:

Perform “Get” Operation

	private static String processGetRequest(URL url, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
		SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
		HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
		con.setSSLSocketFactory(sslFactory);
		con.setRequestMethod("GET");
		con.addRequestProperty("x-ms-version", "2012-03-01");
		InputStream responseStream = (InputStream) con.getContent();
		String response = getStringFromInputStream(responseStream);
		responseStream.close();
		return response;
	}

Perform “Post” Operation

	private static int processPostRequest(URL url, byte[] data, String contentType, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
		SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
		HttpsURLConnection con = null;
		con = (HttpsURLConnection) url.openConnection();
		con.setSSLSocketFactory(sslFactory);
		con.setDoOutput(true);
		con.setRequestMethod("POST");
		con.addRequestProperty("x-ms-version", "2012-03-01");
		con.setRequestProperty("Content-Length", String.valueOf(data.length));
		con.setRequestProperty("Content-Type", contentType);
		
		DataOutputStream  requestStream = new DataOutputStream (con.getOutputStream());
		requestStream.write(data);
		requestStream.flush();
		requestStream.close();
		return con.getResponseCode();
	}

Perform “Delete” Operation

	private static int processDeleteRequest(URL url, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
		SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
		HttpsURLConnection con = null;
		con = (HttpsURLConnection) url.openConnection();
		con.setSSLSocketFactory(sslFactory);
		con.setRequestMethod("DELETE");
		con.addRequestProperty("x-ms-version", "2012-03-01");
		return con.getResponseCode();

Working Examples

Here are some working examples. They are not complete but should give you an idea about how to go about performing some operations:

List Locations

This is based on the documentation here: http://msdn.microsoft.com/en-us/library/windowsazure/gg441293.aspx. This makes use of “processGetRequest” helper function.

			String subscriptionId = "fd9a283a-3a98-b17e-a2b8-763cf6e9ba18";
			String keyStorePath = "C:\\Program Files\\Java\\jre7\\bin\\WindowsAzureKeyStore.jks";
			String keyStorePassword = "test123";
			String url = "";

			//List locations
			url = String.format("https://management.core.windows.net/%s/locations", subscriptionId);
			String response = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
			System.out.println(response);

and here’s the output:

<Locations xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Location>
    <Name>Southeast Asia</Name>
    <DisplayName>Southeast Asia</DisplayName>
    <AvailableServices>
      <AvailableService>Compute</AvailableService>
      <AvailableService>Storage</AvailableService>
      <AvailableService>PersistentVMRole</AvailableService>
      <AvailableService>HighMemory</AvailableService>
    </AvailableServices>
  </Location>
  <Location>
    <Name>East Asia</Name>
    <DisplayName>East Asia</DisplayName>
    <AvailableServices>
      <AvailableService>Compute</AvailableService>
      <AvailableService>Storage</AvailableService>
      <AvailableService>PersistentVMRole</AvailableService>
      <AvailableService>HighMemory</AvailableService>
    </AvailableServices>
  </Location>
  <Location>
    <Name>North Central US</Name>
    <DisplayName>North Central US</DisplayName>
    <AvailableServices>
      <AvailableService>Compute</AvailableService>
      <AvailableService>Storage</AvailableService>
    </AvailableServices>
  </Location>
  <Location>
    <Name>North Europe</Name>
    <DisplayName>North Europe</DisplayName>
    <AvailableServices>
      <AvailableService>Compute</AvailableService>
      <AvailableService>Storage</AvailableService>
      <AvailableService>PersistentVMRole</AvailableService>
      <AvailableService>HighMemory</AvailableService>
    </AvailableServices>
  </Location>
  <Location>
    <Name>West Europe</Name>
    <DisplayName>West Europe</DisplayName>
    <AvailableServices>
      <AvailableService>Compute</AvailableService>
      <AvailableService>Storage</AvailableService>
      <AvailableService>PersistentVMRole</AvailableService>
      <AvailableService>HighMemory</AvailableService>
    </AvailableServices>
  </Location>
  <Location>
    <Name>West US</Name>
    <DisplayName>West US</DisplayName>
    <AvailableServices>
      <AvailableService>Compute</AvailableService>
      <AvailableService>Storage</AvailableService>
      <AvailableService>PersistentVMRole</AvailableService>
      <AvailableService>HighMemory</AvailableService>
    </AvailableServices>
  </Location>
  <Location>
    <Name>East US</Name>
    <DisplayName>East US</DisplayName>
    <AvailableServices>
      <AvailableService>Compute</AvailableService>
      <AvailableService>Storage</AvailableService>
      <AvailableService>PersistentVMRole</AvailableService>
      <AvailableService>HighMemory</AvailableService>
    </AvailableServices>
  </Location>
</Locations>

You can then simply parse the XML to get desired information.

Create Cloud Service

This is based on the documentation here: http://msdn.microsoft.com/en-us/library/windowsazure/gg441304.aspx. This makes use of “processPostRequest” helper function.

			String subscriptionId = "fd9a283a-3a98-b17e-a2b8-763cf6e9ba18";
			String keyStorePath = "C:\\Program Files\\Java\\jre7\\bin\\WindowsAzureKeyStore.jks";
			String keyStorePassword = "test123";
			String url = "";
			String cloudServiceName = "cloudserviceusingjava";
			String label = "my awesome cloud service in java";
			String description = "my awesome cloud service in java";
			String location = "Southeast Asia";
			url = String.format("https://management.core.windows.net/%s/services/hostedservices", subscriptionId);
			String requestBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?><CreateHostedService xmlns=\"http://schemas.microsoft.com/windowsazure\"><ServiceName>%s</ServiceName><Label>%s</Label><Description>%s</Description><Location>%s</Location></CreateHostedService>";
			requestBody = String.format(requestBody, cloudServiceName, Base64.encodeBase64String(label.getBytes()), description, location);
			int createResponseCode = processPostRequest(new URL(url), requestBody.getBytes(), "application/xml", keyStorePath, keyStorePassword);
			System.out.println(createResponseCode);

If the request process properly, you should get back 201 as “responseCode”.

Since the code above required me to convert a string into Base64 format, I made use of “apache.common.codecs” which you can download from here: http://commons.apache.org/proper/commons-codec/download_codec.cgi.

Delete Cloud Service

This is based on the documentation here: http://msdn.microsoft.com/en-us/library/windowsazure/gg441305.aspx/. This makes use of “processDeleteRequest” helper function.

			String subscriptionId = "fd9a283a-3a98-b17e-a2b8-763cf6e9ba18";
			String keyStorePath = "C:\\Program Files\\Java\\jre7\\bin\\WindowsAzureKeyStore.jks";
			String keyStorePassword = "test123";
			String url = "";
			String cloudServiceToDelete = "cloudserviceusingjava";
			url = String.format("https://management.core.windows.net/%s/services/hostedservices/%s", subscriptionId, cloudServiceToDelete);
			int deleteResponseCode = processDeleteRequest(new URL(url), keyStorePath, keyStorePassword);
			System.out.println(deleteResponseCode);

If the request process properly, you should get back 200 as “responseCode”.

Complete Code

Here’s the complete code:

import java.io.IOException;
import java.net.*;
import java.security.*;
import java.io.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.KeyStoreException;
import java.security.UnrecoverableKeyException;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import org.apache.commons.codec.binary.Base64;

public class ServiceManagementRESTHelper {

	private static KeyStore getKeyStore(String keyStoreName, String password) throws IOException
	{
		KeyStore ks = null;
		FileInputStream fis = null;
		try {
			ks = KeyStore.getInstance("JKS");
			char[] passwordArray = password.toCharArray();
			fis = new java.io.FileInputStream(keyStoreName);
			ks.load(fis, passwordArray);
			fis.close();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			if (fis != null) {
				fis.close();
			}
		}
		return ks;
	}
	
	private static SSLSocketFactory getSSLSocketFactory(String keyStoreName, String password) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException, IOException {
		KeyStore ks = getKeyStore(keyStoreName, password);
		KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
		keyManagerFactory.init(ks, password.toCharArray());

		  SSLContext context = SSLContext.getInstance("TLS");
		  context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());

		  return context.getSocketFactory();
	}
	
	// Source - http://www.mkyong.com/java/how-to-convert-inputstream-to-string-in-java/
	private static String getStringFromInputStream(InputStream is) {
		 
		BufferedReader br = null;
		StringBuilder sb = new StringBuilder();
 
		String line;
		try {
 
			br = new BufferedReader(new InputStreamReader(is));
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
 
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
 
		return sb.toString();
 
	}
	
	private static String processGetRequest(URL url, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
		SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
		HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
		con.setSSLSocketFactory(sslFactory);
		con.setRequestMethod("GET");
		con.addRequestProperty("x-ms-version", "2012-03-01");
		InputStream responseStream = (InputStream) con.getContent();
		String response = getStringFromInputStream(responseStream);
		responseStream.close();
		return response;
	}
	
	private static int processPostRequest(URL url, byte[] data, String contentType, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
		SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
		HttpsURLConnection con = null;
		con = (HttpsURLConnection) url.openConnection();
		con.setSSLSocketFactory(sslFactory);
		con.setDoOutput(true);
		con.setRequestMethod("POST");
		con.addRequestProperty("x-ms-version", "2012-03-01");
		con.setRequestProperty("Content-Length", String.valueOf(data.length));
		con.setRequestProperty("Content-Type", contentType);
		
		DataOutputStream  requestStream = new DataOutputStream (con.getOutputStream());
		requestStream.write(data);
		requestStream.flush();
		requestStream.close();
		return con.getResponseCode();
	}
	
	private static int processDeleteRequest(URL url, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
		SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
		HttpsURLConnection con = null;
		con = (HttpsURLConnection) url.openConnection();
		con.setSSLSocketFactory(sslFactory);
		con.setRequestMethod("DELETE");
		con.addRequestProperty("x-ms-version", "2012-03-01");
		return con.getResponseCode();
	}
	
	public static void main(String[] args)
	{
		try {
			String subscriptionId = "fd9a283a-3a98-b17e-a2b8-763cf6e9ba18";
			String keyStorePath = "C:\\Program Files\\Java\\jre7\\bin\\WindowsAzureKeyStore.jks";
			String keyStorePassword = "test123";
			String url = "";

			//List locations
			url = String.format("https://management.core.windows.net/%s/locations", subscriptionId);
			String response = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
			System.out.println(response);
			
			//Create cloud service
			String cloudServiceName = "cloudserviceusingjava";
			String label = "my awesome cloud service in java";
			String description = "my awesome cloud service in java";
			String location = "Southeast Asia";
			url = String.format("https://management.core.windows.net/%s/services/hostedservices", subscriptionId);
			String requestBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?><CreateHostedService xmlns=\"http://schemas.microsoft.com/windowsazure\"><ServiceName>%s</ServiceName><Label>%s</Label><Description>%s</Description><Location>%s</Location></CreateHostedService>";
			requestBody = String.format(requestBody, cloudServiceName, Base64.encodeBase64String(label.getBytes()), description, location);
			int createResponseCode = processPostRequest(new URL(url), requestBody.getBytes(), "application/xml", keyStorePath, keyStorePassword);
			System.out.println(createResponseCode);
			//Delete cloud service
			String cloudServiceToDelete = "cloudserviceusingjava";
			url = String.format("https://management.core.windows.net/%s/services/hostedservices/%s", subscriptionId, cloudServiceToDelete);
			int deleteResponseCode = processDeleteRequest(new URL(url), keyStorePath, keyStorePassword);
			System.out.println(deleteResponseCode);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Acknowledgement

As I told you above I haven’t worked with Java in ages and I had to search through many Internet sites to get the information I wanted. StackOverflow obviously had been a great help however one site I want to mention in particular is http://www.mkyong.com. This site has some really helpful blog posts on Java.

Summary

That’s it for this post. I hope you will find this information useful. As always, please let me know if I have made any mistakes and I will correct them ASAP.

Happy Coding!!!


[This is the latest product I'm working on]

Comments

  1. Thanks for the great article,

    I tried to use your code using Eclipse IDE but it had some problems. Though I included Apache Common Codecs 1.9 it still get an error in line 141 of the completed code at “encodeBase64String”. When I changed to “encodeBase64″ it displayed no error. However, when I run the code, it just worked for the first part “List locations”, the others two parts “Create cloud service” and “Delete cloud service”. I received the 400 response code for “Create cloud service” and 404 code for “delete cloud service”.

    Could you please help me?
    Thanks

    • 400 error usually means there’s a problem with the request payload. Can you share the code for creating/deleting cloud service and I will take a look?

      • Hi Gaurav,

        Thanks for your quick response. I remain most of your completed code, I just did some changes in the “main” function by replacing my subscription id, keyStorePath, keyStorePassword, and changed “encodeBase64String” to “encodeBase64″. Here is my “main” function:

        public static void main(String[] args)
        {
        try {
        String subscriptionId = “f4b8d961-a5dc-489b-8a67-bastb51bb3be”;
        String keyStorePath = “C:\\Users\\shifu_000\\WindowsAzureKeyStore.jks”;
        String keyStorePassword = “xxxxxx”;
        String url = “”;

        //List locations

        System.out.println(“Listing locations”);
        url = String.format(“https://management.core.windows.net/%s/locations”, subscriptionId);
        String response = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
        System.out.println(response);
        System.out.println();

        //Create cloud service

        System.out.println(“Creating cloud service”);
        String cloudServiceName = “cloudserviceusingjava”;
        String label = “my awesome cloud service in java”;
        String description = “my awesome cloud service in java”;
        String location = “Southeast Asia”;
        url = String.format(“https://management.core.windows.net/%s/services/hostedservices”, subscriptionId);
        String requestBody = “%s%s%s%s”;
        requestBody = String.format(requestBody, cloudServiceName, Base64.encodeBase64(label.getBytes()), description, location);
        int createResponseCode = processPostRequest(new URL(url), requestBody.getBytes(), “application/xml”, keyStorePath, keyStorePassword);
        System.out.println(createResponseCode);
        System.out.println();

        //Delete cloud service

        System.out.println(“Deleting cloud service”);
        String cloudServiceToDelete = “cloudserviceusingjava”;
        url = String.format(“https://management.core.windows.net/%s/services/hostedservices/%s”, subscriptionId, cloudServiceToDelete);
        int deleteResponseCode = processDeleteRequest(new URL(url), keyStorePath, keyStorePassword);
        System.out.println(deleteResponseCode);

        } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }
        }

        And here is the output:

        Listing locations
        East AsiaEast AsiaComputeStoragePersistentVMRoleHighMemorySoutheast AsiaSoutheast AsiaComputeStoragePersistentVMRoleHighMemoryNorth EuropeNorth EuropeComputeStoragePersistentVMRoleHighMemoryWest EuropeWest EuropeComputeStoragePersistentVMRoleHighMemoryEast USEast USComputeStoragePersistentVMRoleHighMemoryWest USWest USComputeStoragePersistentVMRoleHighMemoryJapan EastJapan EastComputeStoragePersistentVMRoleHighMemoryJapan WestJapan WestComputeStoragePersistentVMRoleHighMemory

        Creating cloud service
        400

        Deleting cloud service
        404

        Thanks again,

        Nguyen

        • 404 error on deleting cloud service is understandable because the cloud service is not created yet. It seems the XML formatting is getting lost when you post the code in comments. Will it be possible for you to email me the request body XML (value of requestBody variable)? My email is gaurav @ cynapta.com. I’ll take a look. Thx.

          • Hi Gaurav,

            Thanks for your response.
            Sorry, I didn’t check the comment carefully, the XML format was lost. I’ve just sent the request body XML to your email. In addition, the third part “Delete a cloud service” works fine. I used it to successfully delete a cloud service I manually created before.

            Thanks,
            Nguyen

          • Hi Gaurav,
            Sorry for the delay in response. As your suggestion via email, I found the problem is caused by changing encodeBase64String to encodeBase64. However, when I changed back to encodeBase64String, Eclipse display an error at the code. It seems to have no encodeBase64String in libraries though I have imported the Apache Common Codec. After checking libraries in Eclipse, I realize that I am using an older version of Apache Common Codecs. I then remove the old version and use version 1.9. Now I can use encodeBase64String and everything works great.

            Thanks so much for your help Gaurav and hope anyone who get the same problem can find this helpful.

            Cheers,
            Nguyen

  2. Nirman Rathod says:

    Hi Gaurav,
    I am facing an issue. I get the following error:
    Server returned HTTP response code: 403 for URL: https://management.core.windows.net/
    when i make an azure REST call from Junits. The first @Test always fails giving the above error. All other subsequent requests give proper results and Tests pass.

    I have followed the same steps as above for making the API calls. Is there any change in the environment which causes this error ?

  3. Hi Gaurav,
    I get following error with my code:
    java.io.IOException: Server returned HTTP response code: 400 for URL:
    https://management.core.windows.net/39d15643-047a-476b-8254-cf9c8d0a7a71/locations
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.URLConnection.getContent(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getContent(Unknown Source)
    at ServiceManagementREST.processGetRequest(ServiceManagementREST.java:87)
    at ServiceManagementREST.main(ServiceManagementREST.java:133)

    I have followed the same steps as above for making the API calls. How can I solve it.
    Thank you very much。

    • Can you share your complete code? 400 error usually means there’s something wrong from your side.

      • import java.io.IOException;
        import java.net.*;
        import java.security.*;
        import java.io.*;
        import java.security.KeyManagementException;
        import java.security.NoSuchAlgorithmException;
        import java.security.KeyStoreException;
        import java.security.UnrecoverableKeyException;
        import javax.net.ssl.HttpsURLConnection;
        import javax.net.ssl.KeyManagerFactory;
        import javax.net.ssl.SSLContext;
        import javax.net.ssl.SSLSocketFactory;
        import org.apache.commons.codec.binary.Base64;
         
        public class ServiceManagementREST {
         
            private static KeyStore getKeyStore(String keyStoreName, String password) throws IOException
            {
                KeyStore ks = null;
                FileInputStream fis = null;
                try {
                    ks = KeyStore.getInstance("JKS");
                    char[] passwordArray = password.toCharArray();
                    fis = new java.io.FileInputStream(keyStoreName);
                    ks.load(fis, passwordArray);
                    fis.close();
                     
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                finally {
                    if (fis != null) {
                        fis.close();
                    }
                }
                return ks;
            }
             
            private static SSLSocketFactory getSSLSocketFactory(String keyStoreName, String password) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException, IOException {
                KeyStore ks = getKeyStore(keyStoreName, password);
                KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
                keyManagerFactory.init(ks, password.toCharArray());
         
                  SSLContext context = SSLContext.getInstance("TLS");
                  context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
         
                  return context.getSocketFactory();
            }
             
            // Source - http://www.mkyong.com/java/how-to-convert-inputstream-to-string-in-java/
            private static String getStringFromInputStream(InputStream is) {
                  
                BufferedReader br = null;
                StringBuilder sb = new StringBuilder();
          
                String line;
                try {
          
                    br = new BufferedReader(new InputStreamReader(is));
                    while ((line = br.readLine()) != null) {
                        sb.append(line);
                    }
          
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (br != null) {
                        try {
                            br.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
          
                return sb.toString();
          
            }
             
            private static String processGetRequest(URL url, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
                SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
                HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
                con.setSSLSocketFactory(sslFactory);
                con.setRequestMethod("GET");
                con.addRequestProperty("x-ms-version", "2010-10-29");
                InputStream responseStream = (InputStream) con.getContent();
                String response = getStringFromInputStream(responseStream);
                responseStream.close();
                return response;
            }
             
            private static int processPostRequest(URL url, byte[] data, String contentType, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
                SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
                HttpsURLConnection con = null;
                con = (HttpsURLConnection) url.openConnection();
                con.setSSLSocketFactory(sslFactory);
                con.setDoOutput(true);
                con.setRequestMethod("POST");
                con.addRequestProperty("x-ms-version", "2014-08-26");
                con.setRequestProperty("Content-Length", String.valueOf(data.length));
                con.setRequestProperty("Content-Type", contentType);
                 
                DataOutputStream  requestStream = new DataOutputStream (con.getOutputStream());
                requestStream.write(data);
                requestStream.flush();
                requestStream.close();
                return con.getResponseCode();
            }
             
            private static int processDeleteRequest(URL url, String keyStore, String keyStorePassword) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException {
                SSLSocketFactory sslFactory = getSSLSocketFactory(keyStore, keyStorePassword);
                HttpsURLConnection con = null;
                con = (HttpsURLConnection) url.openConnection();
                con.setSSLSocketFactory(sslFactory);
                con.setRequestMethod("DELETE");
                con.addRequestProperty("x-ms-version", "2014-08-26");
                return con.getResponseCode();
            }
             
            public static void main(String[] args)
            {
                try {
                    String subscriptionId = "39d15643-047a-476b-8254-cf9c8d0a7a71";
                    String keyStorePath = "C:\\WindowsAzureKeyStore.jks";
                    String keyStorePassword = "test123";
                    
                    String url = "";
                    
                    //List locations
                    url = String.format("https://management.core.windows.net/%s/locations", subscriptionId);
                    URLEncoder.encode(url,"UTF-8");
                    String response = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
                    System.out.println(response);
                    
                    System.out.println("Listing locations");
                    url = String.format("https://management.core.windows.net/%s/locations", subscriptionId);
                    String response1 = processGetRequest(new URL(url), keyStorePath, keyStorePassword);
                    System.out.println(response1);
                    System.out.println();
                     
                    //Create cloud service
                    String cloudServiceName = "cloudserviceusingjava";
                    String label = "my awesome cloud service in java";
                    String description = "my awesome cloud service in java";
                    String location = "Southeast Asia";
                    url = String.format("https://management.core.windows.net/%s/services/hostedservices", subscriptionId);
                    String requestBody = "%s%s%s%s";
                    requestBody = String.format(requestBody, cloudServiceName, Base64.encodeBase64String(label.getBytes()), description, location);
                    int createResponseCode = processPostRequest(new URL(url), requestBody.getBytes(), "application/xml", keyStorePath, keyStorePassword);
                    System.out.println(createResponseCode);
                    //Delete cloud service
                    String cloudServiceToDelete = "cloudserviceusingjava";
                    url = String.format("https://management.core.windows.net/%s/services/hostedservices/%s", subscriptionId, cloudServiceToDelete);
                    int deleteResponseCode = processDeleteRequest(new URL(url), keyStorePath, keyStorePassword);
                    System.out.println(deleteResponseCode);
                     
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
      • I’m a little bit on your code changes,just change the subscriptionId and keyStorePath.

      • Can we user Azure SDK for Java to get the information about virtual machines from Azure.

      • Thank you very much.I have a try

        • Hi Gaurav,

          I am the same code which you have posted except the changes in keystore path, password and subscription id. but I am getting the following error. Please let me know I f I am doing some thing wrong.
          java.net.UnknownHostException: management.core.windows.net
          at java.net.PlainSocketImpl.connect(Unknown Source)
          at java.net.Socket.connect(Unknown Source)
          at java.net.Socket.connect(Unknown Source)
          at sun.net.NetworkClient.doConnect(Unknown Source)
          at sun.net.www.http.HttpClient.openServer(Unknown Source)
          at sun.net.www.http.HttpClient.openServer(Unknown Source)
          at sun.net.www.protocol.https.HttpsClient.(Unknown Source)
          at sun.net.www.protocol.https.HttpsClient.New(Unknown Source)
          at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(Unknown Source)
          at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
          at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
          at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
          at java.net.URLConnection.getContent(Unknown Source)
          at sun.net.www.protocol.https.HttpsURLConnectionImpl.getContent(Unknown Source)
          at sample.ServiceManagementRESTHelper.processGetRequest(ServiceManagementRESTHelper.java:89)
          at sample.ServiceManagementRESTHelper.main(ServiceManagementRESTHelper.java:133)

          • Hi Sanjeeva,

            It looks like the URL is not being created properly or you have a problem with your Internet connection connecting with Service Management API endpoint. Can you check if neither of them are the reason for this?

  4. Hi Gaurav,

    We are using Windows Azure JAVA SDK for a few operations like Creating Storage Account, Uploading & Downloading a Page Blob programmatically. For rest of the operations like VM Life cycle management we use Azure REST API’s directly.

    We are stuck with an issue with Download (Page Blob – VHD File) – Download is stuck in between without throwing any error/exception
    Downloading directly from Azure portal works fine. Using JAVA SDK, out of 6 GB file, around 1 or 2 GB was downloaded, after which it stalls.

    API Used (package com.microsoft.azure.storage.blob;)
    public final void download(final OutputStream outStream, final AccessCondition accessCondition, BlobRequestOptions options, OperationContext opContext) throws StorageException

    We suspect:
    – Some issue with HTTP Socket and READ timeout – Can you please point us to setting right parameters to come out of this.

    Tried manipulating few values like (BlobRequestOptions) but that didn’t help:
    – setMaximumExecutionTimeInMs
    – setTimeoutIntervalInMs
    – setRetryPolicyFactory

    Sample code for reference:
    //Create CloudStorageAccount (Using StorageCredentialsAccountAndKey)
    //Create CloudBlobClient
    //Get reference to Container
    //Create CloudPageBlob – Get page blob reference
    //Set Blob request options
    //Trigger Cloud Page Download

    BlobRequestOptions options = new BlobRequestOptions();
    //Setting complete transaction timeout to 6 hrs – In case it is stuck atleast it comes out after 6 hours
    options.setTimeoutIntervalInMs(6*60*60*1000);
    options.setConcurrentRequestCount(2);
    options.setRetryPolicyFactory(new RetryLinearRetry());

    LOG.debug(“Starting download … “);

    pageBlob.download(outputStream, null, options, null);
    outputStream.close();

    Any help in this regard would be of great help..

    Thanks,
    Kriti

    • Not really work in Java so I may be wrong here but I see that you’re writing entire 6 GB into outputStream. Could it be possible that you’re running into some kind of buffer overflow here? One thing I would certainly recommend is do a chunked download (may be download 4 MB chunk at a time), write that data to a file and then download the next chunk and append that chunk to the file. Hope this helps.

      • Thanks for the reply.
        Chunking is taken care internally by Windows Azure Java SDK. So that is the reason we are not doing it specifically in our application. Because of the same reason, there is no scope of buffer overflow as well.

        Moreover, download is successfully executed on most of the test beds. On just a few, it hangs.. Reason why it is stuck can be related to Network bandwidth/unstable connection but we need to make sure our application exits gracefully out of it. So we are looking for a correct parameter which points to Time Out.

        Thanks again.

Trackbacks

  1. Windows Azure Community News Roundup #74…

    Welcome to the latest edition of our weekly roundup of the latest community-driven news, content and…

Speak Your Mind

*