1

FINAL EDIT: The answer has been found. It was a dependency issue. Read answer below.

I'm working on a program that eventually should push data from an SQL server db real-time to our power BI report. I'm currently at a stage where I try to connect to my power BI from my client app.

For the authentication process I've followed this example for the code: https://gist.github.com/dquig/a4f2f02fe3e306cebe2e The authentication seems to be working fine. I'm getting an accesstoken (which is the same everytime, I haven't found yet if this is as supposed to be). EDIT: I also checked all of the msdn pages for OAuth2, powerBI API (including the Azure Active Directory steps).

EDIT: I've just noticed I even get an accesstoken if I fill in complete nonsense (why didn't I try this before... ). What I get is the same token everytime. The Response for the webrequest has a 200 status but a null entity.

Here is my code for authentication (I've left out the request here):

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.microsoft.aad.adal4j.AuthenticationContext;

public class PowerBIController {

private static final String POWER_BI_BASE_URL = "https://api.powerbi.com";
private static final String AUTH_URI = "https://login.windows.net/common/oauth2/authorize";
private static final String RESOURCE_URI = "https://analysis.windows.net/powerbi/api";
private static final boolean VALIDATE_AUTHORITY = false;

private static final String NATIVE_CLIENT_ID = "4b2f0d69-c17d-4d61-b2c0-4aeee5dfffe8";
private static final String USER_AT_TENANT = "powerBIUser@pveermanvicrea.onmicrosoft.com";
private static final String PASSWORD = "****";

private AuthenticationContext context = null;
private Client client;
private ExecutorService service = null;
private Response response;

public PowerBIController() throws Exception {
    client = ClientBuilder.newClient();
    service = Executors.newSingleThreadExecutor();
    context = new AuthenticationContext(AUTH_URI, VALIDATE_AUTHORITY, service);
    String powerBIAccessToken = getToken(RESOURCE_URI, NATIVE_CLIENT_ID, USER_AT_TENANT, PASSWORD);
}

private String getToken(String resourceUri, String nativeClientId,
        String tenant, String password) throws ExecutionException, InterruptedException{
    return context.acquireToken(
            resourceUri,
            nativeClientId,
            tenant,
            password,
            null
    ).get().getAccessToken();
}

Then comes the http request: I tried copy-pasting the whole example (from the link above) but readEntity is not a method of Response. I found the following post on this Read response body in JAX-RS client from a post request. But I am using version 2.0 of javax.ws.rs. So, here is a little confusion for me.

public PowerBIController() throws Exception {
    client = ClientBuilder.newClient();
    service = Executors.newSingleThreadExecutor();
    context = new AuthenticationContext(AUTH_URI, VALIDATE_AUTHORITY, service);
    String powerBIAccessToken = getToken(RESOURCE_URI, NATIVE_CLIENT_ID, USER_AT_TENANT, PASSWORD);    
    post(biTarget, powerBIAccessToken);
}
private void post(WebTarget biTarget, String powerBIAccessToken) throws URISyntaxException, IOException, ExecutionException, InterruptedException {
    Response response = target
    Invocation.Builder builder = biTarget.request(MediaType.APPLICATION_JSON);
    Invocation.Builder header = builder.header("Authorization",
                                               "Bearer " +    powerBIAccessToken);
    response = header.get();
    System.out.println("header: " + header.toString());
    System.out.println("status: " + response.getStatus());
    System.out.println("body:" + response.readEntity(String.class));
}

I've checked at http://docs.powerbi.apiary.io/. Here I have to log in to my Office 365 account and then I can use the same code to get the list of datasets. Here I don't have to authenticate, which could make the difference but when I run as debug I can clearly see I have an accesstoken. Here is the code they say can call the get request properly. Obviously this doesn't work I'm also quite sure the target has typos:

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.powerbi.com/beta/myorghttps://api.powerbi.com/beta/myorg/datasets{?defaultRetentionPolicy}")
  .request(MediaType.TEXT_PLAIN_TYPE)
  .header("undefined", "")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

I've tried using Fiddler to see what is actually happening when I run. However, Fiddler is showing no activity at all (even though I checked the https option).

Finally here are my dependencies for this code:

<dependency>
  <groupId>javax.ws.rs</groupId>
   <artifactId>javax.ws.rs-api</artifactId>
  <version>2.0</version>
</dependency>
<dependency>
  <groupId>org.jboss.resteasy</groupId>
   <artifactId>resteasy-client</artifactId>
  <version>3.0.2.Final</version>
</dependency>
<dependency>
  <groupId>com.microsoft.azure</groupId>
   <artifactId>adal4j</artifactId>
  <version>1.0.0</version>
</dependency>

I'm really looking forward to any help. If anything is wrong with my question please say so. I tried my best to be clear and follow the rules of this forum but I might've missed something.

Much thanks in advance

ANSWER: I was also using azure-media 0.6.0 for parts of my program. This includes a jersey-core 1.3.1. Conclusion: Even though I thought I was importing from javax.ws.rs 2.0 (which it even said if you looked at the type) It was actually getting its object definitions from jersey 1.3.1. This held for more than just the azure-media dependency.

So I will post the dependencies that needed exclusions and the eventual dependencies which were necessary.

<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-management</artifactId>
<version>0.7.0</version>
<exclusions>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
    </exclusion>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-json</artifactId>
    </exclusion>
</exclusions>
</dependency>
<dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-servicebus</artifactId>
<version>0.7.0</version>
<exclusions>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
    </exclusion>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-json</artifactId>
    </exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-serviceruntime</artifactId>
<version>0.6.0</version>
<exclusions>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
    </exclusion>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-json</artifactId>
    </exclusion>
</exclusions>
</dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-media</artifactId>
<version>0.6.0</version>
<exclusions>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
    </exclusion>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-json</artifactId>
    </exclusion>
</exclusions>
</dependency>

The necessary dependencies:

<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.2.Final</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>adal4j</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.19</version>
</dependency>
</dependencies>
Community
  • 1
  • 1
Paternostro
  • 43
  • 2
  • 9

2 Answers2

1

So, the problem was that I used several Maven dependencies which had partially overlapping dependencies in their hierarchy.

For example, I included the Jersey client v2.1.9 as well as the microsoft windows azure API, which uses a Jersey client v1.13.

The key point of this answer is as follows: When you're working with Azure SDK and Power BI REST API, there is a really high chance of you getting messed up dependencies. Check your dependency hierarchy to see which dependencies are used more than once.

Paternostro
  • 43
  • 2
  • 9
0

Is this a typo?

Response response =client.target("https://api.powerbi.com/beta/myorghttps://api.powerbi.com/beta/myorg/datasets{?defaultRetentionPolicy}")

Here is a completed step by step article: https://msdn.microsoft.com/en-US/library/dn877545.aspx, for Power BI Authentication, refer to 'What you need to authenticate a Power BI client app' section.

  • That is probably a typo. However, that is not what I put in my code. I tried it, and it errors. Thanks for the link, but I've checked all of the msdn pages. The examples are all for c# though. I believe I've followed all the steps of the authentication. Like I said, I DO get a token. I just get an empty Response entity. – Paternostro Jul 07 '15 at 06:34
  • Glad to see you have fixed the issue, actually I have followed the document and ever made it work. General steps are: 1. Create user in AAD and ensure the group has an organization user. 2. Register power BI via that user. 3. Add app in AAD with configuring its Client ID and redirect urls. 4. Use the code (you have referenced) and complete the project. –  Jul 07 '15 at 11:12
  • I have another controller in which a Configuration Object is taken from the OLD jersey version.. However, this problem is solved by putting an order on the dependencies. i.e. I had to put the dependencies with the older version last. – Paternostro Jul 07 '15 at 11:50
  • Cool, obviously it would be better if you can summarize those key points and post an answer under your question, will be benefit for others who have a similar inquiry. –  Jul 08 '15 at 15:10
  • Thanks for the advice, I posted an answer. Is my answer complete according to SO conventions? – Paternostro Jul 14 '15 at 06:59