I am interested in writing a Java application that can access my OneNote notebooks via the OneNote API. I am not sure how to gain access to that API from within Java. Can anybody point me to an example of how to get started here? I use Eclipse as my development environment.
This as straightforward process.
The 3 steps would be:
1) create a OneNote application on the OneNote developper's page. More info here https://dev.onedrive.com/app-registration.htm. This is a one time action.
2) your java application should then provide an authentification mechanism and a tolken-refresh mechanism.
See this post for more info on the authentification mechanism part : Getting a OneNote token with Java. This post is about the OAuth 2.0 flow 'Authorization code grant flow'. More info here https://msdn.microsoft.com/en-us/library/hh243647.aspx#flows
3) your java application calls adhoc API Rest methods to retreive the needed informations.
Example to retrieve all your notebooks (using OkHttp for Http requests):
private final static String NOTEBOOKS_ENDPOINT = "https://www.onenote.com/api/v1.0/me/notes/notebooks";
public Notebooks readAllNoteBooks() {
try {
if (client == null)
client = new OkHttpClient();
Request request = createOneNoteRequest(a_valid_tolken, NOTEBOOKS_ENDPOINT);
Response response = client.newCall(request).execute();
JsonObject content = UrlHelper.parseResponse(response);
System.out.println(content);
return Notebooks.build(content.get("value"));
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Request createOneNoteRequest(String mAccessToken, String url) {
Request.Builder reqBuilder = new Request.Builder();
reqBuilder.url(url);
reqBuilder.header("Authorization", "Bearer " + mAccessToken);
return reqBuilder.build();
}
NoteBooks and NoteBook are 2 tiny classes matching the key attributes from the OneNote objects.
Microsoft has provided REST apis for accessing One note functionalities like creating and accessing notes. See OneNote Rest API reference.
singrass,
In addition to the above replies, the Android OneNote API sample may also help you. There is no OneNote application class that you can create (unless you want to create your own). You simply call the API through the HttpClient. If you are unfamiliar on how to call REST APIs in Java in general, this thread may help you.
-- James
Related
I have a monolithic legacy application that I need to read and submit data to. It's using Google Web Kit and Java Servlets.
I have access to the source code, but I'm new to both Servlets and GWT.
I'm trying to encapsulate a rest client in my project that can communicate with GET/POST rest calls to the legacy server.
I've been able to send a POST request using Postman, and then used Reactive Spring 5.0 framework to sending that request.
When I try to deserialize the response, I'm running into a ton of errors.
How would I deserialize this payload?
7|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|1|2|3|4|2|5|5|6|7|
I've searched all day, and followed a few blogs like these:
https://docs.google.com/document/d/1eG0YocsYYbNAtivkLtcaiEE5IOF5u4LUol8-LL0TIKU/edit#
https://blog.gdssecurity.com/labs/2009/10/8/gwt-rpc-in-a-nutshell.html
I'm not sure code wise how I can serialize them into my own object for my new service.
static WebClient webClient = WebClient.create();
public static void main(String[] args) {
Mono<String> body = Mono.just("7|0|7|http://localhost:8080/testproject/|29F4EA1240F157649C12466F01F46F60|com.test.client.GreetingService|greetServer|java.lang.String|myInput1|myInput2|1|2|3|4|2|5|5|6|7|");
Mono<String> response = webClient.post()
.uri("http://localhost:8080/testproject/")
.header("Content-Type", "text/x-gwt-rpc;charset=UTF-8")
.header("X-GWT-Module-Base", "http://localhost:8080/testproject/")
.header("X-GWT-Permutation", "29F4EA1240F157649C12466F01F46F60")
.cookie("JSESSIONID", "2BCEBF12GE2C3A0335F5012812A73638")
.body(body, String.class)
.retrieve()
.bodyToMono(String.class);
String unBlocked = response.block();
System.out.println(unBlocked);
//OK[1,1,["java.lang.Integer/3438228391"],0,2]
try {
ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(
Thread.currentThread().getContextClassLoader(), null);
streamReader.prepareToRead(unBlocked);
System.out.println(streamReader.readObject());
} catch ( Exception e) {
e.printStackTrace();
}
}
Error:
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: This application is out of date, please click the refresh button on your browser. ( Malformed or old RPC message received - expecting version between 5 and 7 )
I've tried every version of GWT because of the malformed RCP message.
Also, I tried to stick it into a string, which I'm sure is failing on its own.
You are trying to decode the server response with the code meant decode the client request. At present they use a different format for historical reasons - note how the response starts with "//OK", but the request has the version/flags/stringcount "7|0|7" beginning.
In at least a small part this is because when a client calls a server, it needs to describe what version it is speaking and where the server should find the file listing the set of classes that the client expects are allowed to be serialized. When the server responds, since the client already told it about the typed that can be serialized, it doesn't need to tell the client the same thing again.
Reading the com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader class and its docs will show the response format and how it can be decoded into objects. There is presently no server-side code that I'm aware of that is intended to do this job, but could probably be written with fairly little difficulty, just some persistence.
I have a Spring Boot application that (among other things) gets some data from a third party JSON API (secured with OAuth), processes the result and presents it to the user. The application receives approx. 1 request each second.
Unfortunately this process is very slow at the moment (and in many cases even ends with a 503 error) and I am looking for some idea to improve the implementation. (by the way: the third party API itself does not seem to be the bottleneck as a instance of my app running on my local machine using the exact same API response very fast at the same time that the deploy instance takes very long).
For the API call I use the Apache HTTP library - or more specifically the Async HTTP Client:
this.httpClientAsync = HttpAsyncClients.custom()
.setDefaultCredentialsProvider(credsProvider) //for forward proxy
.build();
And the actual call to the API is this:
updateToken(); //get or update OAuth Token
HttpGet httpget = new HttpGet(URL);
httpget.addHeader("Authorization", "Bearer " + accessToken);
Future<HttpResponse> f = this.httpClientAsync.execute(httpget, callback);
Do you have any suggestion on how to improve the implementation?
To be honest, I don't even have an idea where the bottleneck is at the moment. Any idea on how to find out about that?
Thanks for your hints!
One more thing/update:
the Spring Controller looks something like this:
#RequestMapping(value = "/api/v1/api_data")
public DeferredResult<ResponseEntity<Map>> getAPIData() throws IOException, InterruptedException {
DeferredResult<ResponseEntity<Map>> res = new DeferredResult<>();
triggerAPICall(new FutureCallback() {
public void completed(Object o) {
(...)
res.setResult(...);
}
(...)
}
return res;
}
Furthermore, I was originally not using the async version of the HTTP client, but the blocking version. This then even slowed down the rest of the application...
I have the following code:
Class<OAuthHandler> _tempClass = (Class<OAuthHandler>) Class.forName(providerClass);
Constructor<OAuthHandler> oAuthHandlerConstructor = _tempClass.getDeclaredConstructor(Vertx.class);
OAuthHandler oAuthHandler = oAuthHandlerConstructor.newInstance(vertx);
OAuth2Auth oAuth2Auth = oAuthHandler.getoAuth2Auth();
/* AccessToken accessToken = */ oAuth2Auth.getToken(oAuthHandler.getTokenConfig(code), accessTokenResponse -> {
if (accessTokenResponse.failed()) {
System.out.println("Failed to obtain token");
} else {
AccessToken accessToken = accessTokenResponse.result();
// Return the token? Somehow.
}
});
The oAuthHandler is a provider specific implementation providing some config etc based on the provider name, and simply wraps around the methods provided by the vertx-auth-oauth2 library.
I would like to use the access token after it returns, but not inside the getToken Lambda, so I can get any information about the user I need.
Ive seen some things about Vert.x Futures, but unsure if I can even use them here, any suggestions or examples to solutions would be much appreciated!
Vert.x OAuth2 support is not vendor specific. According to the documentation http://vertx.io/docs/vertx-web/java/#_oauth2authhandler_handler you will see that the same code can handle the following providers:
Google
Twitter
Github
LinkedIn
Facebook
Keycloak
and as soon as 3.4 is released some small fixes will make it also compatible with:
Azure AD
Also the handler is generic so if you have your own provider you can also use it.
Now regarding the second part of the question how to use the the token directly, then you probably do not want the OAuth2Handler since it hides all this from you and you want to interact with OAuth2 client directly:
http://vertx.io/docs/vertx-auth-oauth2/java/#_getting_started
From the documentation above there is an getting started code example that allows you to interact with the get token without using reflection. This is way better since you will not be hurt if internal api's change.
I'm trying to get the title of a document using the file ID. Here's the code:
private static void printFile(Drive service, String fileId) {
try {
File file = service.files().get(fileId).execute();
System.out.println("Title: " + file.getTitle());
} catch (IOException e) {
System.out.println("An error occured: " + e);
}
}
}
However, when I run it I receive a 403 forbidden error that states, "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
I assume that I have to authenticate, but seeing as I'm completely new to Google Drive API and also java, I'm confused as to how to do this (forgive me). I found this webpage: https://developers.google.com/drive/web/auth/web-server which explains how to authenticate but I'm still confused. The page lists multiple classes that do thing such as exchange the authorization code for an access token and use OAuth 2.0 credentials.
My question is do I need to use all of these classes to authenticate? And how do I implement them into my code?
Here is a brief explanation at the http level.
Any Google Drive REST API call requires an http Authorization: Bearer xxxxxx to be set. If there is no such header, you'll get the 403 you're experiencing
The xxxxx is an access token. There are a myriad ways to get one of these depending on the user experience you want to implement and whether you're trying to access the user's Drive files or the application's. Read the Google docs and experiment with the OAuth Playground.
The Google Java library attempts to abstract all of the above. Whether it does a good job or not is for you to decide. Personally I've had more success calling the REST API directly.
If a user has already authorized our app for OAuth 1 (so we have a valid token/secret pair for this user), is it possible to get a valid OAuth 2.0 access token without the user having to explicitly re-authorize our app again? I know that some APIs support this (e.g. Soundcloud and I think also Google), but I haven't found anything related to OAuth token migration in the Dropbox API documentation.
Context: We have an application in Java that accesses the Dropbox API with OAuth 1.0a using the Scribe OAuth library and want to migrate to the official Dropbox Java API that only supports OAuth 2 (and we don't want to have all our users having to re-authorize us).
Just for people stumbling upon this, the API for this is now there: https://www.dropbox.com/developers/core/docs#oa2-from-oa1
From their Java SDK, I used their Upgrader class like so
DbxOAuth1Upgrader upgrader;
DbxOAuth1AccessToken oAuth1AccessToken;
try {
DbxRequestConfig requestConfig = new DbxRequestConfig("Your App", Locale.getDefault().toString());
DbxAppInfo appInfo = new DbxAppInfo(DROPBOX_APP_KEY, DROPBOX_APP_SECRET);
upgrader = new DbxOAuth1Upgrader(requestConfig, appInfo);
oAuth1AccessToken = new DbxOAuth1AccessToken(oauth1AccessKey, oauth1AccessSecret);
String newToken = upgrader.createOAuth2AccessToken(oAuth1AccessToken);
upgrader.disableOAuth1AccessToken(oAuth1AccessToken);
return newToken;
} catch (Exception e) {
//deal with it
}
It's snipped for relevance but if you're doing this in Android, make sure you do it inside an AsyncTask otherwise it throws an exception for performing work on the main thread.
See also the answer on the Dropbox forum: https://forums.dropbox.com/topic.php?id=107766. For now, there's no automated way today to do this migration.