Read and write Email using Microsoft Graph API Java - java

I want to read and send email using Microsoft Graph API. I have tried using DeviceCodeCredentials and it is working fine but I want to read emails without any user interaction in the backend. By Using, DeviceCodeCredentials it asks me to login using my email id and enter the code provided.
below I the code I have written with ClientSecretCredentials which give me below error.
Exception in thread "main" java.lang.RuntimeException: Unable to get access token
at com.eclerx.email.AccessProvider.accessToken(AccessProvider.java:30)
at com.eclerx.email.AuthenticationBuilder2.main(AuthenticationBuilder2.java:55)
Caused by: java.util.concurrent.ExecutionException:
com.microsoft.aad.msal4j.MsalServiceException: AADSTS1002012: The provided value for scope
User.read openid profile offline_access Mail.Read is not valid. Client credential flows must
have a scope value with /.default suffixed to the resource identifier (application ID URI).
Trace ID: ac0c217d-72c7-4ba0-9472-16c711ceea00
Correlation ID: 4d9f5a16-e2e6-4c26-a30e-40e3aa89d53b
Timestamp: 2022-08-10 13:15:35Z
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
at com.eclerx.email.AccessProvider.accessToken(AccessProvider.java:27)
... 1 more
Caused by: com.microsoft.aad.msal4j.MsalServiceException: AADSTS1002012: The provided value
for scope User.read openid profile offline_access Mail.Read is not valid. Client credential
flows must have a scope value with /.default suffixed to the resource identifier (application
ID URI).
Trace ID: ac0c217d-72c7-4ba0-9472-16c711ceea00
Correlation ID: 4d9f5a16-e2e6-4c26-a30e-40e3aa89d53b
Timestamp: 2022-08-10 13:15:35Z
at
com.microsoft.aad.msal4j.MsalServiceExcepti
onFactory.fromHttpResponse(MsalServiceExceptionFactory.java:45)
at
Code is as below
import java.util.Arrays;
import java.util.List;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.azure.identity.DeviceCodeCredential;
import com.azure.identity.DeviceCodeCredentialBuilder;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.Message;
import com.microsoft.graph.models.User;
import com.microsoft.graph.requests.GraphServiceClient;
import com.microsoft.graph.requests.MessageCollectionPage;
import okhttp3.Request;
public class AuthenticationBuilder2 {
private static final String CLIENT_ID = "*************";
private static final String CLIENT_SECRET_ID = "**************";
private static final String CLIENT_SECRET = "****************";
private static final String AUTH_TENANT = "*************";
private static final List<String> graphApiScopes = Arrays.asList("Mail.Read","User.read");
public AuthenticationBuilder2() {
}
public static AccessProvider initializeGraphForUserAuth() {
ClientSecretCredential clientSecretCredential =
new ClientSecretCredentialBuilder()
.clientId(CLIENT_ID)
.clientSecret(CLIENT_SECRET)
.tenantId(AUTH_TENANT)
.build();
/*final DeviceCodeCredential deviceCodeCred = new DeviceCodeCredentialBuilder()
.clientId(CLIENT_ID)
.tenantId(AUTH_TENANT)
.challengeConsumer(challange -> System.out.println(challange.getMessage()))
.build();*/
TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(graphApiScopes, clientSecretCredential);
//TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(graphApiScopes, deviceCodeCred);
GraphServiceClient<Request> graphServiceClient = GraphServiceClient.builder()
.authenticationProvider(tokenCredentialAuthProvider)
.buildClient();
return new AccessProvider(graphServiceClient, tokenCredentialAuthProvider);
}
public static void main(String[] args) {
AccessProvider accessProvider = AuthenticationBuilder.initializeGraphForUserAuth();
// get token
System.out.println("token : " + accessProvider.accessToken());
System.out.println(accessProvider.getServiceClient().users());
User user = accessProvider.getServiceClient().me().buildRequest().get();
System.out.println("My UserName :: "+user.displayName);
final MessageCollectionPage messagePage = accessProvider.getServiceClient().me().messages()
.buildRequest().top(3).select("subject").get();
List<Message> messageList = messagePage.getCurrentPage();
for(Message msg : messageList) {
System.out.println("Subject -> "+msg.subject);
}
}
}

You are using the client credential flow here, which means that you cannot dynamically request scopes. You must configure your required permission scopes on your app registration in apps.dev.microsoft.com, then you set the value of scope in your code to https://graph.microsoft.com/.default.
please use string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
ref doc - https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-acquire-token?tabs=dotnet#azure-ad-v10-resources
https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=CS#client-credentials-provider
Hope this will help , please let us know if have any question
Thanks

Related

How to get spotify user details with details of another user clinet info

I am trying create one application from where I can get the all the information related to user/Tracks/Album.
I have used below code for authentication using clientid and client secret id.
private static String clintId = "generated id";
private static String clientSecretId = "generated secret id";
private static final URI redirectUri = SpotifyHttpManager.makeUri("http://localhost:8080/api/get-user-code/");
public static final SpotifyApi spotifyApi = new SpotifyApi.Builder()
.setClientId(clintId)
.setClientSecret(clientSecretId)
.setRedirectUri(redirectUri)
.build();
#GetMapping("login")
#ResponseBody
public String spotifyLogin(){
AuthorizationCodeUriRequest authorizationCodeUriRequest = spotifyApi.authorizationCodeUri()
.scope("user-read-private user-read-email user-top-read user-library-read user-library-modify")
.show_dialog(true)
.build();
final URI uri = authorizationCodeUriRequest.execute();
return uri.toString();
}
#GetMapping(value="get-user-code")
public void getSpotifyUserCode(#RequestParam("code") String userCode, HttpServletResponse response) throws IOException {
AuthorizationCodeRequest authorizationCodeRequest = spotifyApi.authorizationCode(userCode)
.build();
try {
final AuthorizationCodeCredentials authorizationCodeCredentials = authorizationCodeRequest.execute();
// Set access and refresh token for further "spotifyApi" object usage
System.out.println("Access token::"+authorizationCodeCredentials.getAccessToken());
spotifyApi.setAccessToken(authorizationCodeCredentials.getAccessToken());
spotifyApi.setRefreshToken(authorizationCodeCredentials.getRefreshToken());
System.out.println("Expires in: " + authorizationCodeCredentials.getExpiresIn());
} catch (IOException | SpotifyWebApiException | org.apache.hc.core5.http.ParseException e){
System.out.println("Error: " + e.getMessage());
}
response.sendRedirect("http://localhost:3000/home");
}
Now take one example: Suppose I have created above client id and secret id from User A (From development dashboard) so for User A everything is working fine like I am able to get user profile, Track etc.
But suppose if I try to get same details for User B like user profile/tracks etc with User A generated client id and secret id then not able to get those information for User B its showing "forbidden".
So my question is that how to get those information for user B (with user A client id and secret details)?

Using an stsclient assumed role with cognito in java

I am using Java.
I have an aws user (sts client) on which I do an "assume role" before trying to call cognito "list users".
The assume role seem to be working fine. However, the "list users" is throwing an error ("The security token included in the request is invalid") and I don't know why. Here is the full error trace:
software.amazon.awssdk.services.cognitoidentityprovider.model.CognitoIdentityProviderException: The security token included in the request is invalid. (Service: CognitoIdentityProvider, Status Code: 400, Request ID: XXX-XXX-XXX)
at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:125)
at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleResponse(CombinedResponseHandler.java:82)
at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:60)
at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:41)
at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:40)
at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:30)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:73)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:42)
at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:78)
at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:40)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:50)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:36)
at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:81)
at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:36)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:56)
at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:36)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.executeWithTimer(ApiCallTimeoutTrackingStage.java:80)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:60)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:42)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:48)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:31)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:37)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:26)
at software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient$RequestExecutionBuilderImpl.execute(AmazonSyncHttpClient.java:193)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.invoke(BaseSyncClientHandler.java:103)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.doExecute(BaseSyncClientHandler.java:167)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.lambda$execute$1(BaseSyncClientHandler.java:82)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.measureApiCallSuccess(BaseSyncClientHandler.java:175)
at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.execute(BaseSyncClientHandler.java:76)
at software.amazon.awssdk.core.client.handler.SdkSyncClientHandler.execute(SdkSyncClientHandler.java:45)
at software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler.execute(AwsSyncClientHandler.java:56)
at software.amazon.awssdk.services.cognitoidentityprovider.DefaultCognitoIdentityProviderClient.listUsers(DefaultCognitoIdentityProviderClient.java:6504)
at EC.RunAWSCall.listUsersFilter(RunAWSCall.java:107)
at EC.RunAWSCall.changingUserMDP(RunAWSCall.java:62)
Here is my code in Java:
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cognitoidentityprovider.model.*;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
import software.amazon.awssdk.services.sts.model.StsException;
import software.amazon.awssdk.services.sts.model.AssumeRoleResponse;
import software.amazon.awssdk.services.sts.model.Credentials;
import software.amazon.awssdk.services.cognitoidentityprovider.CognitoIdentityProviderClient;
public class myClass{
public static void myMainFunction(String role, String envRole, String userPoolId, String clientEmail){
String roleArn = "arn:aws:iam::"+envRole+":role/"+role;
String roleSessionName = "AssumeRoleSession1";
Region region = Region.EU_WEST_1;
StsClient stsClient = StsClient.builder()
.region(region)
.credentialsProvider(ProfileCredentialsProvider.create())
.build();
Credentials myCreds = assumeGivenRole(stsClient, roleArn, roleSessionName);
AwsBasicCredentials awsCreds = AwsBasicCredentials.create(myCreds.accessKeyId(), myCreds.secretAccessKey());
CognitoIdentityProviderClient cognitoClient = CognitoIdentityProviderClient.builder()
.region(region)
.credentialsProvider(StaticCredentialsProvider.create(awsCreds))
.build();
String username = listUsersFilter(cognitoClient, userPoolId, clientEmail);
}
public static Credentials assumeGivenRole(StsClient stsClient, String roleArn, String roleSessionName) {
AssumeRoleRequest roleRequest = AssumeRoleRequest.builder()
.roleArn(roleArn)
.roleSessionName(roleSessionName)
.build();
AssumeRoleResponse roleResponse = stsClient.assumeRole(roleRequest);
Credentials myCreds = roleResponse.credentials();
return myCreds;
}
// Shows how to list users by using a filter.
public static String listUsersFilter(CognitoIdentityProviderClient cognitoClient, String userPoolId, String email) {
String filter = "email = \""+email+"\"";
ListUsersRequest usersRequest = ListUsersRequest.builder()
.userPoolId(userPoolId)
.filter(filter)
.build();
ListUsersResponse response = cognitoClient.listUsers(usersRequest);
response.users().forEach(user -> {
System.out.println("User with filter applied " + user.username() + " Status " + user.userStatus() + " Created " + user.userCreateDate() );
});
return response.users().get(0).username();
}
I don't know why my code isn't working. Especially since I have the exact same code in Python where it's working just fine (though in Python, I explicitly give the sessionToken to cognito, but it doesn't seem to be possible in Java?).
Any idea on what I'm doing wrong?
For comparison, here is the same code in Python which is working:
sts = boto3.client('sts')
assumed_role_object=sts.assume_role(
RoleArn="arn:aws:iam::"+env_role+":role/"+role,
RoleSessionName="AssumeRoleSession1"
)
credentials=assumed_role_object['Credentials']
cognito=boto3.client(
'cognito-idp',
region_name="eu-west-1",
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken'],
)
getUser = cognito.list_users(
UserPoolId=userPoolId,
AttributesToGet=[],
Limit=10,
Filter='email="'+email+'"'
)
It turns out, explicitly giving the sessionToken is also possible in Java. All I need to do is use AwsSessionCredentials instead of AwsBasicCredentials. (Many thanks to the person who answered my question on the aws forum.)

Is it possible to use the DeviceCode authentication Flow with Azure Java SDK?

I successfully generate an IAuthenticationResult using the azure msal4jlibrary - I am presented with a device code, and when that code is typed into a browser, it shows the correct scopes / permissions,
and now I'd like to take this authentication result and pass it into the Azure-SDK authentication similar to:
val result = DeviceCodeFlow.acquireTokenDeviceCode()
val a: Azure = Azure.configure()
.withLogLevel(LogLevel.BODY_AND_HEADERS)
.authenticate(AzureCliCredentials.create(result))
.withDefaultSubscription()
Does anyone know where to look / or any samples which do this?
If you want to use msal4j library to get access token, then use the token to manage Azure resource with Azure management SDK, please refer to the following code
public class App {
public static void main(String[] args) throws Exception {
String subscriptionId = ""; // the subscription id
String domain="";// Azure AD tenant domain
DeviceCodeTokenCredentials tokencred = new DeviceCodeTokenCredentials(AzureEnvironment.AZURE,domain);
Azure azure =Azure.configure()
.withLogLevel(LogLevel.BASIC)
.authenticate(tokencred)
.withSubscription(subscriptionId);
for(AppServicePlan plan : azure.appServices().appServicePlans().list()) {
System.out.println(plan.name());
}
}
}
// define a class to extend AzureTokenCredentials
class DeviceCodeTokenCredentials extends AzureTokenCredentials{
public DeviceCodeTokenCredentials(AzureEnvironment environment, String domain) {
super(environment, domain);
}
#Override
public String getToken(String resource) throws IOException {
// use msal4j to get access token
String clientId="d8aa570a-68b3-4283-adbe-a1ad3c1dfd8d";// you Azure AD application app id
String AUTHORITY = "https://login.microsoftonline.com/common/";
Set<String> SCOPE = Collections.singleton("https://management.azure.com/user_impersonation");
PublicClientApplication pca = PublicClientApplication.builder(clientId)
.authority(AUTHORITY)
.build();
Consumer<DeviceCode> deviceCodeConsumer = (DeviceCode deviceCode) ->
System.out.println(deviceCode.message());
DeviceCodeFlowParameters parameters =
DeviceCodeFlowParameters
.builder(SCOPE, deviceCodeConsumer)
.build();
IAuthenticationResult result = pca.acquireToken(parameters).join();
return result.accessToken();
}
}

Get AWS Cognito user ID in Serverless Java function

I am following the https://serverless-stack.com/ tutorial which uses the Serverless framework to create an API that inserts objects into a DynamoDB table and associates them to the authenticated AWS Cognito user. I am attempting to convert the Node.js code to Java but I have hit a problem when getting the Cognito identity as shown on this page
userId: event.requestContext.identity.cognitoIdentityId,
I expected the following lines of Java code to be equivalent:
final CognitoIdentity identity = context.getIdentity();
final String userId = identity.getIdentityId();
but userId is empty.
I am using the aws-api-gateway-cli-test utility to call my API with credentials of a Cognito user as shown on this page. The authentication passes but the userId is empty in the handler.
This is my function:
package com.mealplanner.function;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.CognitoIdentity;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mealplanner.dal.MealRepository;
import com.mealplanner.domain.Meal;
import com.serverless.ApiGatewayResponse;
public class CreateMealHandler implements RequestHandler<Map<String, Object>, ApiGatewayResponse> {
#Override
public ApiGatewayResponse handleRequest(final Map<String, Object> request, final Context context) {
try {
final CognitoIdentity identity = context.getIdentity();
final String userId = identity.getIdentityId();
final JsonNode body = new ObjectMapper().readTree((String) request.get("body"));
final MealRepository repository = new MealRepository();
final Meal meal = new Meal();
meal.setUserId(userId);
meal.setDescription(body.get("description").asText());
repository.save(meal);
return ApiGatewayResponse.builder()
.setStatusCode(200)
.setObjectBody(meal)
.build();
} catch (final Exception e) {
final String errorText = String.format("Error saving meal with request [%s]", request);
LOGGER.error(errorText, e);
return ApiGatewayResponse.builder()
.setStatusCode(500)
.setObjectBody(errorText)
.build();
}
}
}
And this is the function definition in serverless.yml:
createMeal:
handler: com.mealplanner.function.CreateMealHandler
events:
- http:
path: /meals
method: post
cors: true
authorizer: aws_iam
Am I missing some configuration or have I not translated the Node.js code correctly?
In case I have missed any pertinent information the full code is available here: https://github.com/stuartleylandcole/meal-planner/tree/add-users. I will update this question with anything that is missing to ensure all relevant information is self-contained.
It turns out I hadn't translated the Node.js code correctly. To access the CognitoIdentityId I had to get the requestContext from the request object, then get the identity object, like so:
public ApiGatewayResponse handleRequest(final Map<String, Object> request, final Context context) {
final Map<String, Object> requestContext = (Map<String, Object>) request.get("requestContext");
final Map<String, Object> identity = (Map<String, Object>) requestContext.get("identity");
final String userId = (String) identity.get("cognitoIdentityId");
// etc
}

Hello Analytics API: Java quickstart errors

I'm trying to access data from the Google analytics reporting API using Java.
I was following the "Hello Analytics API: Java quickstart for installed applications" tutorial, and i did everything it tells you, and i get following issues:
com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for everybody: C:\Users\<user>\.store\hello_analytics
com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for owner: C:\Users\timst\.store\hello_analytics
java.lang.NullPointerException
at java.io.Reader.<init>(Reader.java:78)
at java.io.InputStreamReader.<init>(InputStreamReader.java:72)
at com.example.demo.HelloAnalytics.initializeAnalytics(HelloAnalytics.java:60)
at com.example.demo.HelloAnalytics.main(HelloAnalytics.java:44)
I tried using the full path for the client_secret.json.
tried using different methods i found online, but none seem to work.
After getting frustrated by this error i tried the "Hello Analytics API: Java quickstart for service accounts" tutorial.
But here i have the issue that i can't add users to the account, property or view for the accounts i can access.
I have access to other peoples analytics accounts and I can only remove myself from the accounts.
All code I'm using is from the tutorials, using Intellij and gradle.
tl;dr; All I want to do is access the analytics data for all my
accounts, using the reporting API so i can put all this data in my own
database and use this database for my other projects.
the Tutorials google provides doesn't work for me. (the data is mostly Google Adwords data.)
So the Warning is not the problem, it's a known issue with it not working properly on windows.
The java.lang.NullPointerException is because the profile I call to has no rows of data for the given metric. so the return value of the call doesn't have a .getRows() methode because there isn't a row value.
you should check for the row's first,
GaData results;
if (null != results) {
if(results.get("rows") != null){
if (!results.getRows().isEmpty()){
//do something with the rows exp.
for (List<String> row : results.getRows()) {
for (int i=0; i<results.getColumnHeaders().size();i++) {
List<GaData.ColumnHeaders> headers = results.getColumnHeaders();
System.out.println( headers.get(i).getName()+": " + row.get(i));
}
}
}
}
}
In the example I also use the ColumnHeaders, wich you should also check first.
It was also easier to check every single account i had access to and every webProperty and Profile and not just the first value of each of those.
Also, the query explorer is really useful. you should use it to check out which metrics you can use and which dimensions.
Here is my full HelloAnalytics class i just print everything that might be usefull to the console i also use multiple metrics and a dimension from Google AdWords in the getResults methode:
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.analytics.Analytics;
import com.google.api.services.analytics.AnalyticsScopes;
import com.google.api.services.analytics.model.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* A simple example of how to access the Google Analytics API.
*/
public class HelloAnalytics {
// Path to client_secrets.json file downloaded from the Developer's Console.
// The path is relative to HelloAnalytics.java.
private static final String CLIENT_SECRET_JSON_RESOURCE = "/client_secret.json";
// The directory where the user's credentials will be stored.
private static final File DATA_STORE_DIR = new File("out/DataStore/hello_analytics");
private static final File OUTPUT_FILE = new File("out/DataStore/output.text");
private static final String APPLICATION_NAME = "Online Marketing Buddy";
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static NetHttpTransport httpTransport;
private static FileDataStoreFactory dataStoreFactory;
public static void main(String[] args) {
try {
Analytics analytics = initializeAnalytics();
getProfileIds(analytics);
} catch (Exception e) {
e.printStackTrace();
}
}
private static Analytics initializeAnalytics() throws Exception {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
// Load client secrets.
InputStream in =
HelloAnalytics.class.getResourceAsStream(CLIENT_SECRET_JSON_RESOURCE);
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Set up authorization code flow for all auth scopes.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow
.Builder(httpTransport, JSON_FACTORY, clientSecrets,AnalyticsScopes.all())
.setDataStoreFactory(dataStoreFactory)
.build();
// Authorize.
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver())
.authorize("user");
// Construct the Analytics service object.
Analytics response = new Analytics
.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();
return response;
}
private static void getProfileIds(Analytics analytics) throws IOException {
// Get the all view (profile) IDs for the authorized user.
List<String> profileIds = new ArrayList<>();
// Query for the list of all accounts associated with the service account.
Accounts accounts = analytics.management().accounts().list().execute();
if (accounts.getItems().isEmpty()) {
System.err.println("No accounts found");
} else {
for (Account account : accounts.getItems()) {
System.out.println("account: " + account.getName());
String accountId = account.getId();
// Query for the list of properties associated with the each account.
Webproperties properties = analytics.management().webproperties()
.list(accountId).execute();
if (properties.getItems().isEmpty()) {
System.err.println("No properties found for accountId: " + accountId);
} else {
for (Webproperty webproperty : properties.getItems()) {
System.out.println("\nwebproperty: " + webproperty.getName());
String webpropertyId = webproperty.getId();
// Query for the list views (profiles) associated with the property.
Profiles profiles = analytics.management().profiles()
.list(accountId, webpropertyId).execute();
if (profiles.getItems().isEmpty()) {
System.err.println("No views (profiles) found for accoundId: " + accountId + "and webpropertyId: " + webpropertyId);
} else {
// Return the first (view) profile associated with the property.
for (Profile profile : profiles.getItems()) {
System.out.println("\nprofileId added for profile: " + profile.getName());
profileIds.add(profile.getId());
printResults(getResults(analytics,profile.getId()), profile.getId());
}
}
System.out.println("---------- ---------- end webproperty: " + webproperty.getName() + "---------- ----------");
}
}
System.out.println("---------- ---------- end account: " + account.getName() + "---------- ----------");
}
}
}
private static GaData getResults(Analytics analytics, String profileId) throws IOException {
// Query the Core Reporting API for the number of sessions
// in the past 30 days.
GaData data = analytics.data().ga()
.get("ga:" + profileId, "30daysAgo", "yesterday", "ga:adClicks, ga:adCost, ga:transactions, ga:transactionRevenue, ga:users, ga:sessions")
.setDimensions("ga:adwordsCampaignID")
.execute();
return data;
}
private static void printResults(GaData results, String profile) {
// Parse the response from the Core Reporting API for
// the profile name and number of sessions.
if (null != results) {
System.out.println("View (Profile: " + profile + ") Name: "
+ results.getProfileInfo().getProfileName() + "\n");
if (results.get("rows") != null && results.get("columnHeaders") != null) {
if (!results.getRows().isEmpty() && !results.getColumnHeaders().isEmpty()) {
for (List<String> row : results.getRows()) {
for (int i=0; i<results.getColumnHeaders().size();i++) {
List<GaData.ColumnHeaders> headers = results.getColumnHeaders();
System.out.println( headers.get(i).getName()+": " + row.get(i) + "\n");
}
System.out.println("---------- ---------- ----------\n");
}
} else {
System.out.println("No rows or columHeaders empty\n");
}
} else {
System.out.println("No rows or columHeaders\n");
}
}
}
}

Categories