Hot questions for Using Azure in sdk

Question:

I'm using newest Azure java sdk(version 0.6), but I found I have problems when I use service bus configuration "configureWithConnectionString" function. Here is my code below,

//get config
string connectionString = "Endpoint=sb://testservicebusnamespace.servicebus.windows.net/;SharedAccessKeyName=MySharedAccessKey;SharedAccessKey=<this is secret not show>";
config = new Configuration();
ServiceBusConfiguration.configureWithConnectionString(null, config, connectionString);

//create service
service = ServiceBusService.create(config);

And I get connection String from my service bus namespace portal in Azure. But When I run this code, it throws an exception "The key 'SharedAccessKeyName' is not valid for this connection string".

I don't know what's the problem, because I get the connection from Azure portal, and I've checked its content(the SharedAccessKeyName, SharedAccessKey), they are right.

So could anyone help me? Is it my problem or this SDK needs update(because I've heard portal already uses SAS, but SDK still uses ACS to authenticate)?

Thanks very much.


Answer:

It looks like Java Azure SDK(0.6.0) still uses ACS to authenticate. See this github issue comments:

the current SDK works with service bus namespace with ACS auth mode, but not new created servicebus namespace which use SAS token auth mode. we will investigate this issue

and

One workaround is to create the service bus namespace via PowerShell. This seems to enable the ACS auth mode by default. Command is:

New-AzureSBNameSpace -Name MyNameSpace -Location "West Europe"

Take a note of the "DefaultKey" you get after running the command. You need to use that with the ServiceBusConfiguration and I'm not sure if that is available via the Azure management portal. Use "owner" as the authenticationName parameter to the configureWithWrapAuthentication.

Question:

I can see that we can define a secure connection string form portal, and than can access those variables in our application.I found many examples to do it in ASP.NET, like defining the keys in web.config. But i can not find any example focusing on accessing these connection strings defined via portal from Spring Boot app. Any help in that direction would be useful


Answer:

See this article from Stefan: How Application Strings and Connection Strings Work in Azure App Service

Azure app service exposes them in the form of environment variables at runtime to the web app. There is a naming convention in place which makes it easier to retrieve them.

For app settings the name of the corresponding environment variable is prepended with APPSETTING_. For connection strings, it depends on the type of DB that has been configured. See below

  • For SQL Azure it is SQLAZURECONNSTR_
  • For SQL Database hosted on Azure VM it is SQLCONNSTR_
  • For MySQL database it is MYSQLCONNSTR_
  • For any other type of databases it is CUSTOMCONNSTR_

In Java, you can use the System.getenv() function to retrieve the environment variables. Refer the document on how to use this: public static String getenv(String name)

You can pass the environment variable to this function to get it working. For example

String envStr = System.getenv("APPSETTING_TestSetting");

Question:

I am trying to setup Windows Azure Java SDK in Windows 7 machine followed their Wiki setup page https://github.com/Azure/azure-sdk-for-java/wiki/Devbox-Setup

when I run test cases/ trying to access Azure REST webservice URLS, getting below error.

set management.keystore.path=E:/Program Files (x86)/Java/jdk1.7.0_51/jre/lib/security/clientcert.jks

Windows Azure Java SDK keystore path issue

java.lang.IllegalArgumentException: The keystore path cannot be null or empty.
    at com.microsoft.windowsazure.core.utils.SSLContextFactory.create(SSLContextFactory.java:86)
    at com.microsoft.windowsazure.core.utils.SSLContextFactory.create(SSLContextFactory.java:60)
    at com.microsoft.windowsazure.credentials.CertificateCloudCredentials.applyConfig(CertificateCloudCredentials.java:128)
    at com.microsoft.windowsazure.core.pipeline.apache.Exports$2.create(Exports.java:51)
    at com.microsoft.windowsazure.core.pipeline.apache.Exports$2.create(Exports.java:1)
    at com.microsoft.windowsazure.core.DefaultBuilder.build(DefaultBuilder.java:200)
    at com.microsoft.windowsazure.core.pipeline.apache.Exports$3.create(Exports.java:65)
    at com.microsoft.windowsazure.core.pipeline.apache.Exports$3.create(Exports.java:1)
    at com.microsoft.windowsazure.core.DefaultBuilder.build(DefaultBuilder.java:200)
    at com.microsoft.windowsazure.core.DefaultBuilder$1.create(DefaultBuilder.java:138)
    at com.microsoft.windowsazure.core.DefaultBuilder.build(DefaultBuilder.java:200)
    at com.microsoft.windowsazure.Configuration.create(Configuration.java:113)
    at com.microsoft.windowsazure.management.storage.StorageManagementService.create(StorageManagementService.java:47)
    at com.microsoft.windowsazure.management.compute.ComputeManagementIntegrationTestBase.createStorageManagementClient(ComputeManagementIntegrationTestBase.java:63)
    at com.microsoft.windowsazure.management.compute.VirtualMachineOperationsTests.setup(VirtualMachineOperationsTests.java:61)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

java.lang.NullPointerException
    at com.microsoft.windowsazure.management.compute.VirtualMachineOperationsTests.cleanHostedService(VirtualMachineOperationsTests.java:452)
    at com.microsoft.windowsazure.management.compute.VirtualMachineOperationsTests.cleanup(VirtualMachineOperationsTests.java:79)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Answer:

Try switching to the latest release of the Java SDK. I wrote up a very basic how-to guide on getting going with it here that might help you get past your JKS issue. Looks like the namespaces you're using are from an earlier release.

http://azure.microsoft.com/blog/2014/09/15/getting-started-with-the-azure-java-management-libraries/

Question:

I have a public Ip address in Azure that is associated with a load balancer. I am trying to use the Java client to dissociate the LB from the IP.

I have attempted quite a few things but the last attempt was the following:

LoadBalancer lb = myPublicIpAddress.getAssignedLoadBalancerFrontend().parent();
LoadBalancerFrontend frontEnd = myPublicIpAddress.getAssignedLoadBalancerFrontend();
lb.update().updatePublicFrontend(frontEnd.name()).withoutPublicIPAddress().parent().apply()

From this I get the error:

CloudException: Frontend IP Configuration must reference either a Subnet, Public IP Address or Public IP Prefix

myPublicIpAddress is a PublicIpAddress object retrieved directlty from azure. The exception confuses me because the frontend is attatched to a public IP

edit: Also of note, This post here uses Azure commands and goes through the NIC. I've tried to replicate this with the java client but the NIC in my project isn't setup the same and this doesn't work.

To replicate: Create a public IP in Azure. Create a LB in Azure and associate it to the IP. Attempt to dissociate via the method above.


Answer:

The public IP for Azure Load Balancer is not the same as the public IP for Azure VM. The Load Balancer must be created with at least a public IP. It means you do not delete all public IP from the Load Balancer.

To disassociate the public IP from the Load Balancer, you need to delete the IP configuration in the Load Balancer front end. I think the method withoutFrontend(String name) that you have used is the right way. What you should pay attention to is that if you want to delete the public Ip from the Load Balancer, there should be more than one public Ip associated with the Load Balancer. You must leave one public Ip for the Load Balancer at least.

Question:

I have written a stand alone code to get the metrics for Azure Storage Blob Services but i want to get only last 5mins metric how can i get it from $MetricsMinutePrimaryTransactionsBlob please suggest

CloudTable cloudMetric = tableClient.getTableReference(cloud
                .getHourMetricsTable(StorageService.BLOB).getName());
        String partitionFilter2 = TableQuery.generateFilterCondition(
                "PartitionKey", QueryComparisons.EQUAL, "20170602T1400");
        String rowFilter3 = TableQuery.generateFilterCondition("RowKey",
                QueryComparisons.EQUAL, "user;All");
        String combinedFilter = TableQuery.combineFilters(partitionFilter2,
                Operators.AND, rowFilter3);
        TableQuery<MetricsPojo> partitionQuery2 = TableQuery.from(
                MetricsPojo.class).where(combinedFilter);
        for (MetricsPojo capacityMetrics2 : cloudMetric
                .execute(partitionQuery2)) {
            System.out.println(capacityMetrics2);
            System.out.println(capacityMetrics2.getPartitionKey() + "\n"
                    + capacityMetrics2.getRowKey() + "\n"
                    + capacityMetrics2.getTimestamp());

Answer:

According to your description and @FrancisYu-MSFT reply, I wrote a sample code and reproduced your current issue.

Here is my sample code.

String connectionString = String.format("DefaultEndpointsProtocol=http;AccountName=%s;AccountKey=%s", ACCOUNT_NAME, ACCOUNT_KEY);
CloudStorageAccount account = CloudStorageAccount.parse(connectionString);
CloudAnalyticsClient client = account.createCloudAnalyticsClient();
CloudTable metrics = client.getMinuteMetricsTable(StorageService.BLOB);
System.out.println(metrics.getName());
String queryString = TableQuery.combineFilters(
                TableQuery.generateFilterCondition("PartitionKey", QueryComparisons.GREATER_THAN_OR_EQUAL, "20170602T1400"),
                Operators.AND,
                TableQuery.generateFilterCondition("PartitionKey", QueryComparisons.LESS_THAN_OR_EQUAL, "20170602T1420"));
TableQuery<TableServiceEntity> query = TableQuery.from(TableServiceEntity.class).where(queryString);
for(TableServiceEntity entity : metrics.execute(query)) {
    System.out.println(entity.getPartitionKey()+"\t"+entity.getRowKey());
}

Then I got the same issue when running my code, which was caused by the metrics table $MetricsMinutePrimaryTransactionsBlob not exists, so you need to enable the related Diagnostics options to create it, as the figure below.

Question:

I'm using the Azure ARM API and I'm trying to list all publishers by location through the Azure Java SDK, by executing the following code:

import com.microsoft.azure.management.compute.ComputeManagementClient;
import com.microsoft.azure.management.compute.ComputeManagementService;
import com.microsoft.azure.management.compute.models.VirtualMachineImageListPublishersParameters;
import com.microsoft.azure.management.compute.models.VirtualMachineImageResourceList;

@Test
public void testListPublishers() {
    ComputeManagementClient client = ComputeManagementService.create(createConfiguration());
    VirtualMachineImageListPublishersParameters params = new VirtualMachineImageListPublishersParameters();
    params.setLocation("westus");
    VirtualMachineImageResourceList response = client.getVirtualMachineImagesOperations().listPublishers(params);
    ArrayList<VirtualMachineImageResource> resources = response.getResources();
    System.out.println("Found publishers: " + resources.size());
}

This results in the following request:

GET /subscriptions/{some-subscription}/providers/Microsoft.Compute/locations/westus/publishers?api-version=2015-06-15

However, I always get and empty list, no matter the location I put in the publisher parameters. I am able to list other resources with the same client, so it is not an issue in creating the client.

Do you have any suggestions of what I might be doing wrong? Perhaps there is a permission that I don't have?

Thanks!


Answer:

Per my experience, the issue was caused by the application registed on Azure AD has no Reader role. I reproduced the issue, and resolved it via assign a Reader role to the AzureAD app.

There are two way for assigning a Reader role.

  1. Using Azure-CLI with arm mode, and command azure ad role assignment create --objectId <objectId of the aad app> -o Reader -c /subscriptions/<subscriptionId>/

If you don't know the objectId of the AzureAD app, you can command azure ad sp show --search <the aad app name> to review it. If you have no Service Principal (SP) for Azure AD, you can command azure ad sp create <clientId> to create it.

  1. Add the role and user via All settings -> RESOURCE MANAGEMENT -> Users when the application shown on Azure new portal, please see the pics below.

Select a role Reader :

Add a user by searching name:

After assign the Reader role to the aad app, you can list the image publishers as your wish.

Question:

How to check the health of application gateway using java sdk. I need to perform a similar operation like below azure cli command using java sdk:

azure network application-gateway backend-health show "$1" "$2" --json \ | jq -r '.backendAddressPools[].backendHttpSettingsCollection[].servers[] | select(.health == "Healthy") | .address'


Answer:

I tried to get the health value of your pipeline command via the method health() of the class ApplicationGatewayBackendHealthServer of Azure Java SDK, but failed because it seems not to be implemented that I could not get the ApplicationGatewayBackendHealthServer Object via a implementing path from the root class Azure now.

So I tried to search a related REST API to get the response of command azure network application-gateway backend-health show <resource-group-name> <applicationgateway-name> on Azure REST API docs, but also failed that there is not existing.

I tried to research on source code of AzureCLI & other SDK, finally I got the REST APIs as you want from the detail logs azure.details.log of AzureCLI.

The REST API for your needs is as below for 1st step.

https://management.azure.com/subscriptions/<subscriptionId>/resourceGroups/<resource-group-name>/providers/Microsoft.Network/applicationGateways/<applicationGateway-name>/backendhealth?api-version=<api-version>

Doing the POST request for the above REST API with header Authorization: Bearer <accessToken>, you can get the next dynamic REST API from the response header location like below via GET request with header Authorization: Bearer <accessToken>.

https://management.azure.com/subscriptions/<subscriptionId>/providers/Microsoft.Network/locations/<region>/operationResults/<objectId, such as f7bfd1fd-e3ea-42f7-9711-44f3229ff877>?api-version=<api-version>

Here is my sample code.

String AUTHORITY = "https://login.windows.net/<tenantId>";
String clientId = "<client-id on management portal(old), or application-id on Azure new portal>";
String clientSecret = "<client-secret-key>";
String subscriptionId = "<subscriptionId>";
String resourceGroupName = "<resource-group-name>";
String appGatewayName = "<applicationgateway-name>";
String apiVersion = "2016-09-01";
// Getting access token
AuthenticationContext context = null;
AuthenticationResult result = null;
ExecutorService service = null;
service = Executors.newFixedThreadPool(1);
context = new AuthenticationContext(AUTHORITY, false, service);
ClientCredential credential = new ClientCredential(clientId, clientSecret);
Future<AuthenticationResult> future = context.acquireToken("https://management.azure.com/", credential, null);
result = future.get();
String accessToken = result.getAccessToken();
System.out.println(accessToken);

Using 1st step REST API:

// Get the response header `location` from 1st step REST API
OkHttpClient client = new OkHttpClient();
String url = String.format("https://management.azure.com/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/applicationGateways/%s/backendhealth?api-version=%s", subscriptionId, resourceGroupName, appGatewayName, apiVersion);
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, "");
Request request = new Request.Builder().url(url).header("Authorization", "Bearer "+accessToken).post(body).build();
Response response = client.newCall(request).execute();
String location = response.header("Location");
System.out.println(location);

Using 2nd step dynamic REST API:

// Get the response content as the same as the azure-cli command `azure network applicationgateway backend-health show`
Request request2 = new Request.Builder().url(location).header("Authorization", "Bearer " + accessToken).build();
// Notice for the below code, see under the code
Response response2 = client.newCall(request2).execute();
System.out.println(response2.body().string());

Notice: I was able to get the content via POSTMAN, but I got the response content null for the 2nd step using OKHttp/Apache HttpClient/HttpURLConnection in Java. I don't know what happened & why, even the code implemented in Golang/Jquery works fine. It seems to be caused by the implementation of HTTP protocol stack in Java.

Meanwhile, if you got some error information about permission for the above REST APIs, please refer to https://github.com/JamborYao/ArmManagement to solve it.

Hope it helps for you. If you can resolve the 2nd step issue, please share the solution with us, and I will continue to try for solving it.

Question:

I have been trying to write some basic code to test out Azure KeyVault. At the moment (as you can see from the console log), I can authenticate but KeyVaultClient just fails with a [Fatal Error] :1:1: Premature end of file.

There seems to be a bit of a lack of real-world examples from Microsoft in relation to the azure-java-sdk, so I admit I have been struggling a bit doing my best interpreting the JavaDocs !

16:12:02.391 [main] DEBUG com.example.cli.Main - Launched ! 16:12:02.453 [main] DEBUG e.s.cli.AzureAuthenticationResult - Authresult getToken

16:12:02.491 [pool-1-thread-1] DEBUG c.m.aad.adal4j.AuthenticationContext - [Correlation ID: XXXXXXX-XXX-XXX-XXX-XXXXXXX] Using Client Http Headers: x-client-SKU=java;x-client-VER=1.0.0;x-client-OS=XXXX;x-client-CPU=XXXX;return-client-request-id=true;client-request-id=XXXXXXX-XXX-XXX-XXX-XXXXXXX;

16:12:02.491 [pool-1-thread-1] INFO c.m.a.adal4j.AuthenticationAuthority - [Correlation ID: XXXXXXX-XXX-XXX-XXX-XXXXXXX] Instance discovery was successful

16:12:05.142 [pool-1-thread-1] DEBUG c.m.aad.adal4j.AuthenticationContext - [Correlation ID: XXXXXXX-XXX-XXX-XXX-XXXXXXX] Access Token with hash 'ZZZZZZZZZZZZZZZZZZZZZZZZ' returned

[Fatal Error] :1:1: Premature end of file.

16:12:08.135 [main] ERROR com.example.cli.Main - null java.util.concurrent.ExecutionException: com.microsoft.windowsazure.exception.ServiceException: at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[na:1.8.0_45]

at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[na:1.8.0_45]

at com.microsoft.azure.keyvault.FutureAdapter.get(FutureAdapter.java:53) ~[azure-keyvault-0.9.0.jar:na] at com.example.cli.Main.main(Main.java:37) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45] at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45] at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [idea_rt.jar:na]

Caused by: com.microsoft.windowsazure.exception.ServiceException: at >com.microsoft.windowsazure.exception.ServiceException.createFromXml(ServiceException.java:216) ~[azure-core-0.9.0.jar:na] at com.microsoft.azure.keyvault.KeyOperationsImpl.sign(KeyOperationsImpl.java:1524) ~[azure-keyvault-0.9.0.jar:na] at com.microsoft.azure.keyvault.KeyOperationsImpl$13.call(KeyOperationsImpl.java:1447) ~[azure-keyvault-0.9.0.jar:na] at >com.microsoft.azure.keyvault.KeyOperationsImpl$13.call(KeyOperationsImpl.java:1444) ~[azure-keyvault-0.9.0.jar:na] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_45] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_45] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_45] at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_45]

Process finished with exit code 0

package com.example.cli;

import com.microsoft.azure.keyvault.KeyVaultClient;
import com.microsoft.azure.keyvault.KeyVaultClientService;
import com.microsoft.azure.keyvault.models.KeyOperationResult;
import com.microsoft.azure.keyvault.webkey.JsonWebKeySignatureAlgorithm;
import com.microsoft.windowsazure.Configuration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.security.*;

import java.util.Random;

import java.util.concurrent.Future;


public class Main {

    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(Main.class);
        logger.debug("Launched !");

        try {
            byte[] plainText = new byte[100];
            new Random(0x1234567L).nextBytes(plainText);
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(plainText);
            byte[] digest = md.digest();
            Configuration configuration = AzureKVCredentials.createConfiguration();
            KeyVaultClient keyVaultClient = KeyVaultClientService.create(configuration);
            Future<KeyOperationResult> keyOperationPromise;
            KeyOperationResult keyOperationResult;
            keyOperationPromise = keyVaultClient.signAsync("https://XXXXXXX.vault.azure.net/keys/XXXXXXX/XXXXXXX",JsonWebKeySignatureAlgorithm.RS256,digest);
            keyOperationResult = keyOperationPromise.get();   // <=== THIS IS LINE 37 IN THE STACKTRACE   ;-)   <====
            byte[] res = keyOperationResult.getResult();
            String  b64 = java.util.Base64.getEncoder().encodeToString(res);
            logger.debug(b64);


        } catch (Exception e) {
            logger.error(null,e);
        }
    }
}

Answer:

For using Azure KeyVault, you can try to use Azure REST APIs to manage and operate the Key Vault. Please refer to the Key Vault REST document https://msdn.microsoft.com/en-us/library/azure/dn903630.aspx.

There are two set of APIs for Key Vault management and Keys & Secrets operations that need different access tokens from different resource uri.

For management apis, the resource uri is https://management.core.windows.net/.

For operation apis, the resource uri is https://vault.azure.net. (Note: Please notice there is no symbol / at the end of the uri. )

Here is a sample code as references.

package aad.keyvault;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.naming.ServiceUnavailableException;
import javax.net.ssl.HttpsURLConnection;

import org.apache.commons.io.IOUtils;

import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientCredential;

public class RestAPISample {

    private static final String subscriptionId = "<subscription_id>";
    private static final String resourceGroupName = "<resource_group_name>";
    private static final String vaultName = "<vault_name>";
    private static final String apiVersion = "2015-06-01";
    private static final String getKeyVaultInfoUri = String.format(
            "https://management.azure.com/subscriptions/%s/resourceGroups/%s/providers/Microsoft.KeyVault/vaults/%s?api-version=%s",
            subscriptionId, resourceGroupName, vaultName, apiVersion);

    private static final String tenantId = "<tenant_id>";
    private static final String authority = String.format("https://login.windows.net/%s", tenantId);
    private static final String clientId = "<client_id>";
    private static final String clientSecret = "<client_secret_key>";
    private static final String keyName = "<keyvault_key>";
    private static final String getInfoFromAKeyUri = String.format("https://%s.vault.azure.net/keys/%s?api-version=%s",
            vaultName, keyName, apiVersion);

    public static String getAccessToken(String resource)
            throws MalformedURLException, InterruptedException, ExecutionException, ServiceUnavailableException {
        AuthenticationContext context = null;
        AuthenticationResult result = null;
        ExecutorService service = null;
        try {
            service = Executors.newFixedThreadPool(1);
            context = new AuthenticationContext(authority, true, service);
            ClientCredential credential = new ClientCredential(clientId, clientSecret);
            Future<AuthenticationResult> future = context.acquireToken(resource, credential, null);
            result = future.get();
        } finally {
            service.shutdown();
        }
        String accessToken = null;
        if (result == null) {
            throw new ServiceUnavailableException("authentication result was null");
        } else {
            accessToken = result.getAccessToken();
            System.out.println("Access Token: " + accessToken);
        }
        return accessToken;
    }

    public static void getKeyVaultInfo() throws MalformedURLException, IOException, ServiceUnavailableException,
            InterruptedException, ExecutionException {
        System.out.println(getKeyVaultInfoUri);
        HttpsURLConnection conn = (HttpsURLConnection) new URL(getKeyVaultInfoUri).openConnection();
        conn.setRequestProperty("Authorization", "Bearer " + getAccessToken("https://management.core.windows.net/"));
        conn.addRequestProperty("Content-Type", "application/json");
        String resp = IOUtils.toString(conn.getInputStream());
        System.out.println(resp);
    }

    public static void getKeyInfo() throws MalformedURLException, IOException, ServiceUnavailableException, InterruptedException, ExecutionException {
        System.out.println(getInfoFromAKeyUri);
        HttpsURLConnection conn = (HttpsURLConnection) new URL(getInfoFromAKeyUri).openConnection();
        conn.setRequestProperty("Authorization", "Bearer " + getAccessToken("https://vault.azure.net"));
        conn.addRequestProperty("Content-Type", "application/json");
        String resp = IOUtils.toString(conn.getInputStream());
        System.out.println(resp);
    }

    public static void main(String[] args)
            throws InterruptedException, ExecutionException, ServiceUnavailableException, IOException {
        getKeyVaultInfo();
        getKeyInfo();
    }

}

Azure Key Vault operation APIs need different permissions setted by using command set-policy. For example Get information about a key(https://msdn.microsoft.com/en-us/library/azure/dn878080.aspx), it need authorization requires the keys/get permission by using Azure CLI cmd azure keyvault set-policy --vault-name <vault-name> --spn <service-principal-no.> --perms-to-keys '["get"]' to add permission get to keys.

Question:

Using Extended metrics I am trying to retrieve certain metrics for certain VMS. Every query seems to take extremely long, as new records are made for each VM every 15 seconds in the table.

So I'm trying to query the table in the last 5 minutes, but it's not working and giving me an error. Does anyone know how to query these WADMETRICS tables?

My code.

        CloudStorageAccount account = CloudStorageAccount.parse(connectionString);
        CloudTableClient cloudTableClient = account.createCloudTableClient();
        DateTime fiveMinutesAgo = DateTime.now().minusMinutes(5);
        String queryString = TableQuery.generateFilterCondition("Timestamp", TableQuery.QueryComparisons.GREATER_THAN_OR_EQUAL, fiveMinutesAgo.toString());
        TableQuery<TableServiceEntity> query = TableQuery.from(TableServiceEntity.class).where(queryString);

        CloudTable table = cloudTableClient.getTableReference("WADMetricsPT1MP10DV2S20191017");
        System.out.println(table.exists());
        System.out.println(table.getName());
        for (TableServiceEntity entity : table.execute(query)) {
            System.out.println(entity.getPartitionKey() + "\t" + entity.getRowKey());
        }

What I get back when I run this.

An error occurred while enumerating the result, check the original exception for details. java.util.NoSuchElementException: An error occurred while enumerating the result, check the original exception for details. at com.microsoft.azure.storage.core.LazySegmentedIterator.hasNext(LazySegmentedIterator.java:113) at com.optum.oea.workbench.service.RemoteAzureService.getVmMetric(RemoteAzureService.java:138) at com.optum.oea.workbench.service.RemoteAzureService.getVmMetric(RemoteAzureService.java:120) at com.optum.oea.workbench.controller.MetricsController.getMetric(MetricsController.java:75) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at com.optum.oea.workbench.config.WorkbenchAttestationFilter.doFilterInternal(WorkbenchAttestationFilter.java:33) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at com.optum.oea.workbench.config.AuthenticationFilter.doFilter(AuthenticationFilter.java:65) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Caused by: com.microsoft.azure.storage.table.TableServiceException: Bad Request at com.microsoft.azure.storage.table.TableServiceException.generateTableServiceException(TableServiceException.java:52) at com.microsoft.azure.storage.table.CloudTableClient$2.preProcessResponse(CloudTableClient.java:415) at com.microsoft.azure.storage.table.CloudTableClient$2.preProcessResponse(CloudTableClient.java:390) at com.microsoft.azure.storage.core.ExecutionEngine.executeWithRetry(ExecutionEngine.java:138) at com.microsoft.azure.storage.core.LazySegmentedIterator.hasNext(LazySegmentedIterator.java:109)


Answer:

According to my test, if you want to query the WADMETRICS tables by filtering timetap, please refer to the following code:

 CloudStorageAccount account = CloudStorageAccount.parse("connection string");
        CloudTableClient client = account.createCloudTableClient();

        CloudTable table = client.getTableReference("WADMetricsPT1MP10DV2S20191017");
        System.out.println(table.exists());
        System.out.println(table.getName());





        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
        cal.add(Calendar.HOUR, -19);
        cal.add(Calendar.MINUTE,-21);
        Date date = cal.getTime();
//        SimpleDateFormat df = new  SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'");
//        date = df.parse(df.format(date));
//
        System.out.println(date.toString());



        String queryString = TableQuery.generateFilterCondition("Timestamp",TableQuery.QueryComparisons.GREATER_THAN_OR_EQUAL, date);

        TableQuery<TableServiceEntity> query = TableQuery.from(TableServiceEntity.class).where(queryString);
        Iterable<TableServiceEntity> results = table.execute(query);
        int i=0;
        for (TableServiceEntity  entity:results
             ) {
            i +=1;
            System.out.println(entity.getPartitionKey());
        }

        System.out.println(i); 

Besides, you also can query you Azure table on the portal:

Question:

I have a method in my code which is responsible for inserting single documents into cosmosDB. And it used to work fine when i used to insert document without specifying partitionId in RequestOptions:

public Document createOne(JSONObject aJSONObject)  throws DocumentClientException {
    Document aDocument = new Document(aJSONObject.toString());            
    return documentClient.createDocument(getCollectionLink(), aDocument, null, false).getResource();
}

But if i change my code to pass partitionId in RequestOptions like this:

public Document createOne(JSONObject aJSONObject, String aPartitionKeyStr)  throws DocumentClientException {
    Document aDocument = new Document(aJSONObject.toString());

    PartitionKey aPartitionKey = new PartitionKey(aPartitionKeyStr);
    RequestOptions requestOptions = new RequestOptions();
    requestOptions.setPartitionKey(aPartitionKey);

    return documentClient.createDocument(getCollectionLink(), aDocument, requestOptions, false).getResource();
}

I get the above error: PartitionKey extracted from document doesn't match the one specified in the header. I'm pretty sure i'm passing the partition key value correctly as i have the same createMany method which uses a stored procedure for bulk insertion and passes partitionKey in requestOptions, and it's working fine. I've looked up on internet and found similar questions that seemed to be related to my problem like this and this, but they focus on passing the partitionKey correctly. I'm sure i'm passing the partitionKey correctly.

In our collection, /clientId key is used as a partition key, setting the breakpoint at the first line of the insertion function gives this output, and aPartitionKey is printed as follows: ["shiv-postman-client"]

I have one more doubt, would passing partitionKey while inserting a single document would make any improvements in performance? I saw in azure's sdk documentation also here(the example that shows the partitioned collection usage), that they haven't used partition key while insertion, only during querying.


Answer:

For inserting a single document, you don't need to specify a Partition Key value in request options.

If you look at the REST API documentation for Creating a Document, you will notice that there's no x-ms-documentdb-partitionkey header there. This is why your code works when no partition key is specified in request options (which gets sent as request headers).

You would need to specify a PartitionKey value in request options if you are trying to update a document though. See Replace Document REST API.

Question:

Version: 1.1.0

I am creating a VM using a market place image. My code looks something like this

VirtualMachine linuxVM = azure.virtualMachines().define(name)
                .withRegion(Region.US_WEST)
                .withExistingResourceGroup(myRg)
                .withExistingPrimaryNetwork(network)
                .withSubnet("subnet1")
                .withPrimaryPrivateIPAddressDynamic()
                .withNewPrimaryPublicIPAddress("ip-" + name)
                .withLatestLinuxImage("publisher", "offer", "sku")
                .withRootUsername("root")
                .withRootPassword("some password")
                .withSize(VirtualMachineSizeTypes.BASIC_A0)
                .create();

I get an error as follows.

Async operation failed with provisioning state: Failed: Creating a virtual machine from Marketplace image requires Plan information in the request. OS disk name is '<name>'

How do I add plan information?


Answer:

It looks like plan information can be added to the VM create, after spending some time with the source code. The following code works with 1.1.0.

PurchasePlan plan = new PurchasePlan();
plan.withName("name");
plan.withPublisher("publisher");
plan.withProduct("prodcut");

VirtualMachine linuxVM = azure.virtualMachines().define(name)
                .withRegion(Region.US_WEST)
                .withExistingResourceGroup(myRg)
                .withExistingPrimaryNetwork(network)
                .withSubnet("subnet1")
                .withPrimaryPrivateIPAddressDynamic()
                .withNewPrimaryPublicIPAddress("ip-" + name)
                .withLatestLinuxImage("publisher", "offer", "sku")
                .withRootUsername("root")
                .withRootPassword("some password")
                .withSize(VirtualMachineSizeTypes.BASIC_A0)
                .withPlan(plan)
                .create();

Question:

I started using Azure Java SDK 1.0.0 recently and I noticed that for a VM the method osDiskStorageAccountType() always returns null. The SDK is unable to even get information about the attached data disks.


Answer:

From the article we know that osDiskStorageAccountType is only available for managed disk (this is c# based API but I think it will suitable for Java). Here is a snippet:

Gets the storage account type of the managed disk backing Os disk.

If you create Azure VM based on managed disk, it will give you related info.

Question:

I am using simple java sdk code to verify the azure basic connection. I have uploaded the management certificate in the settings in the azure portal. But I am getting the following exception whenever I try to authenticate :

Exception in thread "main" com.microsoft.windowsazure.exception.ServiceException: ForbiddenError: The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription. at com.microsoft.windowsazure.exception.ServiceException.createFromXml(ServiceException.java:206) at com.microsoft.windowsazure.management.LocationOperationsImpl.list(LocationOperationsImpl.java:162) at com.mycompany.testproj1.test1.main(test1.java:46)

When i try to download the certificate using azure cli

$ azure account cert export info: Executing command account cert export error: This subscription does not use a management certificate info: Error information has been recorded to /Users/tt/.azure/azure.err error: account cert export command failed

Is this related to my use of free trial ?


Answer:

The issues are not related to free trial, refer to the first faq of https://azure.microsoft.com/en-us/pricing/free-trial-faq/.

For the limits of Azure Subscription, please refer to https://azure.microsoft.com/en-us/documentation/articles/azure-subscription-service-limits/.

Seems that you can’t use management certificate to manage Azure Services successfully after uploaded management certificate in the settings of Azure Portal.

There is the partial sample code in Java for authenticating Azure Service Management.

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import com.microsoft.windowsazure.Configuration;
import com.microsoft.windowsazure.core.utils.KeyStoreType;
import com.microsoft.windowsazure.management.configuration.ManagementConfiguration;
import com.microsoft.windowsazure.management.compute.ComputeManagementService;
import com.microsoft.windowsazure.management.compute.ComputeManagementClient;
import com.microsoft.windowsazure.management.network.NetworkManagementService;
import com.microsoft.windowsazure.management.network.NetworkManagementClient;

String uri = "https://management.core.windows.net/";
        String subscriptionId = "<your subscription id>";
        String keyStoreLocation = "<KeyStore.jks>";
        String keyStorePassword = "<password for KeyStore>";

        Configuration config = ManagementConfiguration.configure(
                new URI(uri),
                subscriptionId,
                keyStoreLocation, // the file path to the JKS
                keyStorePassword, // the password for the JKS
                KeyStoreType.jks // flags that I'm using a JKS keystore
              );

// For Compute Management
ComputeManagementClient computeManagementClient = ComputeManagementService.create(config);

//For Networing Management
NetworkManagementClient client = NetworkManagementService.create(config);

// Others like above

The code dependents on some maven repositories below in the pom.xml what you need to add in your project.

<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-svc-mgmt</artifactId>
    <version>0.8.3</version>
</dependency>
<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-svc-mgmt-compute</artifactId>
    <version>0.8.3</version>
</dependency>
<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-svc-mgmt-network</artifactId>
    <version>0.8.3</version>
</dependency>

For the error of Azure CLI, I think you missed some necessary steps as below.

Firstly, using command login and Azure username & password to connect your Azure subscription.

$ azure login -u <username@hostname>

Secondly, switching the Azure Service Management Mode for export certificate.

$ azure config mode asm

Lastly, downloading certiticate.

$ azure account cert export

Then, you can find the cert file called <subscription-id>.pem at the current path.

For details, you can refer to https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-connect/.

Any concern for this thread, please feel free to let me know.

Question:

As the answer was Page Not Found, I was trying to retrieve size of Public IPs with the following code

Configuration config = ManagementConfiguration.configure(
          new URI(uri), 
          subscriptionId,
          keyStoreLocation, // the file path to the JKS
          keyStorePassword, // the password for the JKS
          KeyStoreType.jks // flags that I'm using a JKS keystore
        );

NetworkResourceProviderClient  networkResourceProviderClient = NetworkResourceProviderService.create(config);
           PublicIpAddressListResponse PublicIpAddressListResponse =networkResourceProviderClient.getPublicIpAddressesOperations().listAll();
           ArrayList<PublicIpAddress> PublicIpAddressList =PublicIpAddressListResponse.getPublicIpAddresses();
           System.out.println(PublicIpAddressList.size());

using Azure AD ServicePrincipal authentication, It returns - 0

using certificate authentication with the "https://management.azure.com/" API, It returns - AuthenticationFailed:

Exception in thread "main" com.microsoft.windowsazure.exception.ServiceException: AuthenticationFailed: Authentication failed. The 'Authorization' header is not present or provided in an invalid format.
    at com.microsoft.windowsazure.exception.ServiceException.createFromJson(ServiceException.java:290)
    at com.microsoft.azure.management.network.PublicIpAddressOperationsImpl.listAll(PublicIpAddressOperationsImpl.java:1443)
    at com.microsoft.azure.auth.Program.main(Program.java:50)

any Idea how to retrieve all the Virtual Machine's Public IP address? or how to Authenticate it to get the IP value?


Answer:

The issue was caused by using the incorrect authentication.

The authentication code below just works for Azure Service Management.

Configuration config = ManagementConfiguration.configure(
          new URI("https://management.core.windows.net), 
          subscriptionId,
          keyStoreLocation, // the file path to the JKS
          keyStorePassword, // the password for the JKS
          KeyStoreType.jks // flags that I'm using a JKS keystore
        );

Authenticating for Azure Resource Management, the doc "Authenticating Azure Resource Management request"( https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx) says "All of the tasks that you do on resources using the Azure Resource Manager must be authenticated with Azure Active Directory. ".

So you need to modify the authenticate configuration code with your subscription-id, tenant-id, client-id and client-secret as follow:

private static AuthenticationResult getAccessTokenFromServicePrincipalCredentials() throws
            ServiceUnavailableException, MalformedURLException, ExecutionException, InterruptedException {
        AuthenticationContext context;
        AuthenticationResult result = null;
        ExecutorService service = null;
        try {
            service = Executors.newFixedThreadPool(1);
            // TODO: add your tenant id
            context = new AuthenticationContext("https://login.windows.net/" + "<your tenant id>",
                    false, service);
            // TODO: add your client id and client secret
            ClientCredential cred = new ClientCredential("<your client id>",
                    "<your client secret>");
            Future<AuthenticationResult> future = context.acquireToken(
                    "https://management.azure.com/", cred, null);
            result = future.get();
        } finally {
            service.shutdown();
        }

        if (result == null) {
            throw new ServiceUnavailableException(
                    "authentication result was null");
        }
        return result;
    }


Configuration config = ManagementConfiguration.configure(
          null,
          new URI("https://management.core.windows.net), 
          "<your-subscription-id>",
          getAccessTokenFromServicePrincipalCredentials()
.getAccessToken()
        );

The complete authenticate code about ServicePrincipal for Java, please refer to https://github.com/Azure/azure-sdk-for-java/blob/master/azure-mgmt-samples/src/main/java/com/microsoft/azure/samples/authentication/ServicePrincipalExample.java.

For the thread(Retrieve List of networks for a subscription in windows azure with azure java sdk) answer's url, it moves https://github.com/Azure/azure-sdk-for-java/blob/master/service-management/azure-svc-mgmt-network/src/main/java/com/microsoft/windowsazure/management/network/NetworkOperations.java.

Question:

Tried the basic location retriever code (shown below)

String uri = "https://management.core.windows.net/";
        String subscriptionId = "XXXXXXXX-5fad-XXXXXX-9dfa-XXXXXX";
         String keyStoreLocation = "D:\\test.jks";
         String keyStorePassword = "123456";

        Configuration config = ManagementConfiguration.configure(
                  new URI(uri), 
                  subscriptionId,
                  keyStoreLocation, // the file path to the JKS
                  keyStorePassword, // the password for the JKS
                  KeyStoreType.jks // flags that I'm using a JKS keystore
                ); 


        ManagementClient client = ManagementService.create(config);
        // get the list of regions
        LocationsListResponse response = client.getLocationsOperations().list();
        ArrayList<Location> locations = response.getLocations();
        // write them out
        for( int i=0; i<locations.size(); i++){
          System.out.println(locations.get(i).getDisplayName());

    }

and It works fine. But when I try to create the ComputeManagementClient and try to restart a VM

ComputeManagementClient computeManagementClient = ComputeManagementService.create(config);
        VirtualMachineOperations virtualMachinesOperations= computeManagementClient.getVirtualMachinesOperations();
virtualMachinesOperations.restart("SQLVM", "sqlvm.cloudapp.net");

I'm getting the certificate error.

Exception in thread "main" java.util.concurrent.ExecutionException: com.microsoft.windowsazure.exception.ServiceException: ForbiddenError: The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:188)
    at com.microsoft.azure.management.compute.VirtualMachineOperationsImpl.restart(VirtualMachineOperationsImpl.java:9973)
    at com.microsoft.azure.compute.RestartVMExample.main(RestartVMExample.java:84)

PS: I created a the .cer from Java Keystore and uploaded into Azure with no issues.

Any clues what is happening?


Answer:

The issue is caused by using the incorrect Azure Java SDK libraries. When I used the maven dependencies in the file pom.xml below, I reproduced the same exception.

<dependency>
   <groupId>com.microsoft.azure</groupId>
   <artifactId>azure-mgmt-compute</artifactId>
   <version>0.8.3</version>
</dependency>

The library supply the VM restart function need two arguments: resource group name and vm name. But the API of library azure-mgmt-compute is used for Azure Resource Management.

To restart VM, you need to use the API of library azure-svc-mgmt-compute for Azure Service Management if you used JKS certificates. The Class VirtualMachineOperations supply the same name function restart need three arguments: service name, deployment name and vm name. You can find these names from Cloud Service dashboard on Azure Portal. In your issue code, the vm name should be "sqlvm".

The right maven pom.xml for dependencies as below:

<dependency>
   <groupId>com.microsoft.azure</groupId>
   <artifactId>azure-svc-mgmt</artifactId>
   <version>0.8.3</version>
</dependency>
<dependency>
   <groupId>com.microsoft.azure</groupId>
   <artifactId>azure-svc-mgmt-compute</artifactId>
   <version>0.8.3</version>
</dependency>

And the code as below

virtualMachinesOperations.restart("<service name: sqlvm>", "<deployment name: sqlvm>", "<vm name: sqlvm>");

The steps below for genkeypair by using Java Keytool in the path JAVA_HOME/bin:

keytool -genkeypair -alias keyfile -keyalg RSA -keystore <KeyStore.jks> 
-keysize 2048 -storepass "<password>"

keytool -v -export -file <KeyStore.cer> -keystore KeyStore.jks -alias keyfile

My code:

String uri = "https://management.core.windows.net/";
String subscriptionId = "<subscription_id>";
String keyStoreLocation = "KeyStore.jks";
String keyStorePassword = "<password>";

Configuration config = ManagementConfiguration.configure(
       new URI(uri), 
       subscriptionId,
       keyStoreLocation, // the file path to the JKS
       keyStorePassword, // the password for the JKS
       KeyStoreType.jks // flags that I'm using a JKS keystore
    ); 
ComputeManagementClient computeManagementClient = ComputeManagementService.create(config);
VirtualMachineOperations virtualMachinesOperations = computeManagementClient.getVirtualMachinesOperations();
virtualMachinesOperations.restart("petercore", "petercore", "petercore");

Question:

I am using the Azure Java SDK to list available images for creating virtual machines. When I use:

ComputeManagementService.create(config).ComputeManagementClient().getVirtualMachineOSImagesOperations().list().getImages();

It only lists the gallery images available and not my custom images. I have seen other topics that cover SDKs for other languages or using PowerShell but I would like to do this with the Java SDK for Azure.

Does anyone know how to use the Java SDK for Azure to get a list of My Images?

Thanks.


Answer:

David is correct. Please try getVirtualMachineVMImagesOperations. One year ago, VM images have replaced OS images. So all your custom images now are VM images. Please refer to http://azure.microsoft.com/en-us/updates/vm-image-entity/ for more information.

Question:

I've got some Java code to create a new file on an Azure Storage File Service (Azure's SMB file share feature), and I'm trying to add metadata to that com.microsoft.azure.storage.file.CloudFile object:

final HashMap<String, String> metaData = new HashMap<>();
metaData.put("tag", value);
cloudFile.setMetadata(metaData);

If I immediately perform a getMetadata() call on that same CloudFile object, it's there. However, after the program exits and I view the file in Azure Portal, there's no metadata to be seen. I just wrote a separate test program to create a new CloudFile object referencing that file, and it also is unable to retrieve the metadata.

Is there something else I have to do to "persist" my metadata after setting it? BTW, I've successfully done this to Blob Store objects, but this is the first time trying it with File Service objects.


Answer:

Please call uploadMetadata() method after setting the metadata.

So your code would be:

final HashMap<String, String> metaData = new HashMap<>();
metaData.put("tag", value);
cloudFile.setMetadata(metaData);
cloudFile.uploadMetadata();

Question:

I need to remove all blobs from a container. I thought the easy way to do this would be to delete and re-create the container. Not so much...

Here is the code that waits:

while (saClient.getContainerReference(myContainerName.exists()) {
    try {
        Thread.sleep(20 * 1000);
    } catch (InterruptedException ie) {
        Thread.interrupted();
        System.out.println("<: interrupted");
        return;
    }
}

When I come out of that loop, I try to re-create the container and get the exception:

com.microsoft.azure.storage.StorageException: The specified container is being deleted. Try operation later.

I can re-code to delete each blob, but am curious about this interface behavior. I might have the same problem with each blob not really being deleted.

I am using these library versions:

com.microsoft.azure:azure-storage:4.2.0
com.microsoft.azure:azure:1.1.0

Answer:

To answer your question, there's no API call that you can make which will tell you that a container is actually deleted as the deletion process is an asynchronous process.

From the documentation link:

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.

What you would need to do is keep on retrying creating a blob container. If the operation fails with status code 409 and error code ContainerBeingDeleted, that means the container is still being deleted. You could retry the operation after waiting for some time.

I would still recommend delete container approach over deleting each blob in the container as delete container is a single operation while to delete all blobs you will have to make as many operations as there are blobs in that container.

Question:

I have a problem when try to send a message to a service bus topic through java azure sdk, I receive 500 Internal Server Error.

I prepared code based on this link: https://azure.microsoft.com/en-us/documentation/articles/service-bus-java-how-to-use-topics-subscriptions/ and my code looks like below:

Configuration config = ServiceBusConfiguration.configureWithSASAuthentication(
    "NAMESPACE",
    "SAS_NAME",
    "SAS_KEY_VALUE",
    ".servicebus.windows.net");      
ServiceBusContract service = ServiceBusService.create(config);
try {
    BrokeredMessage message = new BrokeredMessage("Message content");
    service.sendTopicMessage("TOPIC_NAME", message);
} catch (ServiceException e) {
    e.printStackTrace();
}

I'm able to send a message with the same config values with .NET code.

And here is the exception that I receive: "com.sun.jersey.api.client.UniformInterfaceException: POST https://NAMESPACE.servicebus.windows.net/TOPIC_NAME/messages?api-version=2013-07 returned a response status of 500 Internal Server Error"

I have also a question about api-version. Why a library put so old api-version in the request? I use the latest version of azure sdk from maven repository:

<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-servicebus</artifactId>
    <version>0.9.3</version>
</dependency>

Answer:

I tried to reproduce your issue, but failed to not get any error information.

According to the REST API "Send Message", the 500 status code means internal error that's not caused by your client source code.

So I think you can try to run the code again.

Could you share more information for helping analyze the issue if you still get the same error or others?

Any concern, please feel free to let me know.

Question:

Well, that's it. I don't know where to start, and everything I find is about REST API, and I would like to do it vía the Java SDK I've downloaded. I only find a javadoc with all the classes and everything but I don't know what to do with all that info.

I'll appreciate so much a minimum example listing my Virtual Hosts or opening a new Virtual Host or something like that.

EDIT: And just found this http://azure.microsoft.com/blog/2014/09/15/getting-started-with-the-azure-java-management-libraries/

Tons of hours searching and 1 minute after I post a question I found it, lol.


Answer:

Here is the answer:

http://azure.microsoft.com/blog/2014/09/15/getting-started-with-the-azure-java-management-libraries/

Just search import com.microsoft.windowsazure.management in Google.

Question:

I am looking to use this SDK - https://github.com/Azure/azure-sdk-for-java. However it seems completely devoid of even simple samples. I searched around on the web and the only examples are of using the REST API directly. Is this SDK even supported?


Answer:

Here's a blog post on the Azure blog site documenting how you can get started using the SDK with Eclipse and Maven. http://azure.microsoft.com/blog/2014/09/15/getting-started-with-the-azure-java-management-libraries/

Here's a video demo of the same sort of functionality in action on Channel 9. Apologies for my nervousness that day. :) http://channel9.msdn.com/Shows/Cloud+Cover/Episode-157-The-Java-SDK-for-Azure-Management-with-Brady-Gaster