Dart cannot access cloud endpoint API - dart

It's frustrating and I'm stuck here for one week and no clue how to fix it ; (
Inspired by Gerwin Sturm's great work (https://github.com/Scarygami/gdg-endpoint-demo) and I like to build the java backend instead.
But unfortunately, every time when I'm trying to call the endpoints API, a NoSuchMethodError error arise.
Exception: NoSuchMethodError : method not found: '_client#0x296594a'
Receiver: Instance of 'Dbentryendpoint'
Arguments: []
Stack Trace: #0 Object.noSuchMethod (dart:core-patch:1737:25)
#1 Dbentryendpoint.listDBEntry (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/packages/google_dbentryendpoint_v1_api/src/browser/dbentryendpoint.dart:162:16)
#2 main.fetch (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/demo.dart:24:20)
#3 main (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/demo.dart:64:8)
Exception: NoSuchMethodError : method not found: '_client#0x296594a'
Receiver: Instance of 'Dbentryendpoint'
Arguments: []
Stack Trace: #0 Object.noSuchMethod (dart:core-patch:1737:25)
#1 Dbentryendpoint.insertDBEntry (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/packages/google_dbentryendpoint_v1_api/src/browser/dbentryendpoint.dart:124:16)
#2 main.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/demo.dart:56:28)
the source code of demo.dart is almost identical to the original one (https://github.com/Scarygami/gdg-endpoint-demo) and I only change the cloudendpint API and web client ID.
import "dart:html";
import 'packages/google_dbentryendpoint_v1_api/dbentryendpoint_v1_api_browser.dart' as gdglib;
import 'packages/google_plus_v1_api/plus_v1_api_browser.dart' as pluslib;
import 'packages/google_oauth2_client/google_oauth2_browser.dart';
final CLIENT_ID = "878766780041.apps.googleusercontent.com";
final SCOPES = ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/plus.me"];
void main() {
var auth = new GoogleOAuth2(CLIENT_ID, SCOPES);
var gdg = new gdglib.Dbentryendpoint(auth);
var plus = new pluslib.Plus(auth);
var container = query("#entries");
var loginButton = query("#login");
var sendButton = query("#send");
InputElement textInput = query("#text");
var authorSpan = query("#author");
pluslib.Person me;
void fetch() {
//gdg.makeAuthRequests = false;
gdg.makeAuthRequests = true;
gdg.listDBEntry(limit:10).then((l) {
container.text = "";
if (l.items != null) {
l.items.forEach((e) {
var p = new ParagraphElement();
var date = e.date.replaceAll("T", " ");
p.text = "$date - ${e.author}: ${e.text}";
container.append(p);
});
}
});
}
loginButton.onClick.listen((Event e) {
auth.login().then((token) {
loginButton.style.display = "none";
plus.makeAuthRequests = true;
plus.people.get("me").then((p) {
me = p;
authorSpan.text = "${me.displayName}:";
authorSpan.style.display = "inline-block";
textInput.style.display = "inline-block";
sendButton.style.display = "inline-block";
sendButton.onClick.listen((Event e) {
var text = textInput.value;
textInput.value = "";
var entry = new gdglib.DBEntry.fromJson({
"author": me.displayName,
"text": text
});
gdg.makeAuthRequests = true;
gdg.insertDBEntry(entry).then((entry) {
fetch();
});
});
});
});
});
on the Google App Engine side, I generate the cloud endpoint class automatically by the GPE and then add the client ID related info:
#Api(name = "dbentryendpoint",
clientIds={Ids.WEB_CLIENT_ID,com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
scopes={"https://www.googleapis.com/auth/userinfo.email"}
)
public class DBEntryEndpoint {
.....
Appreciate for any help!

I think I figure out the way to work around it but I don't know why:
the "generate cloud endpoints" of GPE doesn't generate the path,
for example it generate the method listEntities, not entities.list
the path is necessary to generate resource in
_ah/api/discovery/v1/apis/dbentryendpoint/v1/rest; without path ,there is only schemas and methods, not schemas and resources
without resources, the Dart client generator only export empty
resouces.dart under /commom folder. and the mothods will be inside
entityEndpoints.dart, which cannot correctly recognize the
_client(), which is defined in client.dart under /common.
So the demo.dart cannot find the method.
Question: why the path is ncessary? because GPE dont generate the path automatically, can we have a way to generate the correct dart client file without manually adding the path in google app engine file? Thanks.

The package import does not look correct, try this.
import 'packages:google_dbentryendpoint_v1_api/dbentryendpoint_v1_api_browser.dart' as gdglib;
import 'packages:google_plus_v1_api/plus_v1_api_browser.dart' as pluslib;
import 'packages:google_oauth2_client/google_oauth2_browser.dart';

Related

Missing Configuration File For Tests - Aqueduct

When implementing OAuth with aqueduct I mistakenly didn't follow the test driven development ideology, and I am paying for it now...
When I run my tests, I get the error:
"No configuration file found. See README.md."
Which is thrown from the initializeApplication method in my AppSink class.
As I understand it, tests make use of the config.src.yaml file so I have configured my test harness accordingly:
application = new Application<OdexSink>();
application.configuration.port = 0;
application.configuration.configurationFilePath = "config.src.yaml";
Since I was able to run the tests before I implemented the AuthServer etc, I suspect it happened along the way.
My test setUp is as follows:
var app = new Application<OdexSink>();
TestClient client;
setUp(() async {
await app.start(runOnMainIsolate: true);
client = new TestClient(app);
var ctx = ManagedContext.defaultContext;
var builder = new SchemaBuilder.toSchema(ctx.persistentStore, new Schema.fromDataModel(ctx.dataModel), isTemporary: true);
for (var cmd in builder.commands) {
await ctx.persistentStore.execute(cmd);
}
});
And my Test harness start() method is:
Future start() async {
RequestController.letUncaughtExceptionsEscape = true;
application = new Application<OdexSink>();
application.configuration.port = 0;
application.configuration.configurationFilePath = "config.src.yaml";
await application.start(runOnMainIsolate: true);
await createDatabaseSchema(ManagedContext.defaultContext, sink.logger);
await addClientRecord();
await addClientRecord(clientID: DefaultClientID, clientSecret: DefaultClientSecret);
client = new TestClient(application)
..clientID = DefaultClientID
..clientSecret = DefaultClientSecret;
}
My config.src.yaml file exits, and contains DB information.
Ah, just one small thing - in your setUp method, you are creating and starting an Application instead of that TestApplication harness. It should look like this
var app = new TestApplication();
setUp(() async {
await app.start();
});
All of the other stuff in setUp is already done in your test harness and you can use the TestClient as app.client:
expect(await app.client.request("/endpoint"), hasStatus(200));

Invalid signature when trying to upload to Cloudinary

Using the Node integration provided by cloudinary_npm, I'm getting the following message back when I try to upload:
{ error: { message: 'Invalid Signature t7233823748278473838erfndsjy8234. String to sign - \'timestamp=1439054775\'.', http_code: 401 } }
I retrieve then pass my image to the backend like this:
$scope.previewFile = function() {
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
reader.onloadend = function () {
base64img = reader.result;
preview.src = base64img;
console.log(base64img);
};
};
$scope.submitPic = function() {
$http.post('http://localhost:3000/story/pic', {img: base64img})
.success(function(data){
preview.src = "";
})
.error(function(err){
console.log(err);
});
};
Then in the back, I have the following configuration and routes, both straight from the docs:
var cloudinary = require("cloudinary");
var CLOUD_API_SECRET = require("../constants.js");
cloudinary.config({
cloud_name: 'some_cloud',
api_key: '63789865675995',
api_secret: CLOUD_API_SECRET
});
router.post('/pic', function(req, res, next) {
var img = req.body.img;
cloudinary.uploader.upload(img, function(result) {
});
res.status(200).send('ok');
});
Does anyone recognize what I might be doing wrong? I've been troubleshooting this for hours. I'm at a dead end.
make sure you have placed your cloudinary secret inside a ''(quote/inverted comma).make sure the resulting statement should mean :
var CLOUD_API_SECRET ='some_cloudinary_secret_xxx';
check this value in the js file from where you are fetching this value.
From Java level I fixed this issue by changing the time zone to America/New_York time:
Long time = new Long(System.currentTimeMillis() );
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
Date date = new Date(sdf.format(new Date(time)));
long utcDateInMilliSeconds = date.getTime();
params.put("timestamp", new Long(utcDateInMilliSeconds/1000));
I had this very same error running similar code route on nodejs using cloudinary's sdk.
The issue turned out to be a typo within my API_SECRET.
Like Jeremy said, It's mostly typo or white space in your API secret.
Try to use your API secret directly in the configuration (not via variable)

Executing Local Query with loaded metadata fails

I'm new to breeze, this looks like a bug, but thought I'd ask here in case I just don't get it.
Setup loading metadata:
var metadataStore = new breeze.MetadataStore();
metadataStore.importMetadata(metadata);
queryOptions = new breeze.QueryOptions( {
fetchStrategy: breeze.FetchStrategy.FromLocalCache
});
mgr = new breeze.EntityManager({
serviceName: 'breeze',
metadataStore: metadataStore,
queryOptions: queryOptions
});
Executing local query explicitly works:
var q = breeze.EntityQuery.from("Boards")
.toType('Board')
.where('isImplicit', 'equals', withImplicits)
.orderBy('name');
return manager.executeQueryLocally(q) // returns result
But using query.using doesn't:
var q = breeze.EntityQuery.from("Boards")
.toType('Board')
.where('isImplicit', 'equals', withImplicits)
.orderBy('name');
q = q.using(breeze.FetchStrategy.FromLocalCache)
return manager.executeQuery(q)
UPDATE: To clarify, the above throws an error as it tries to fetchMetdata and there is no endpoint to fetch from. If I monkey patch the code below, it works fine. It seems like if the dataService .hasServerMetadata, you don't need to fetch it. I'm creating a test harness for a breeze adapter, so I want to be able to run without the backend
Looks like problem is this line in EntityManager:
if ( (!dataService.hasServerMetadata ) || this.metadataStore.hasMetadataFor(dataService.serviceName)) {
promise = executeQueryCore(this, query, queryOptions, dataService);
} else {
var that = this;
promise = this.fetchMetadata(dataService).then(function () {
return executeQueryCore(that, query, queryOptions, dataService);
});
}
I believe line should be if( dataService.hasServerMetadata || ..., but being new to Breeze thought I'd ask here before opening GH issue.
EntityManager.executeQueryLocally is a synchronous function and you can use its result immediately. i.e.
var myEntities = myEntityManager.executeQueryLocally(myQuery);
Whereas EntityManager.executeQuery is an asynchonous function ( even if the query has a 'using' call that specifies that this is a local query). So you need to call it like this:
var q2 = myQuery.using(breeze.FetchStrategy.FromLocalCache);
myEntityManager.executeQuery(q2).then(function(data) {
var myEntities = data.results;
});
The idea behind this is that with executeQuery you treat all queries in exactly the same fashion, i.e. asynchronously, regardless of whether they are actually asynchronous under the hood.
If you want to create an EntityManager that does not go to the server for metadata you can do the following:
var ds = new breeze.DataService({
serviceName: "none",
hasServerMetadata: false
});
var manager = new breeze.EntityManager({
dataService: ds
});

simple Google Drive access with Dart

I am trying to read a basic text file(no authorization needed) from google drive with Dart. The code below returns a 400 Error. If the API_KEY is removed then a 403 error. I can input the file id into the Google get file reference page and it will return the metadata correctly.
Any Ideas would be great. Thanks
final url = "https://www.googleapis.com/drive/v2/files/FILE?key={API_KEY}";
var request = new HttpRequest();
request.on.loadEnd.add( (Event e)
{
if (request.status == 200)
{
var data = JSON.parse(request.responseText);
query("#file").text = data;
}
else
{
query("#file").text = "Error ${request.status}: ${request.statusText}";
}
});
request.open("GET", url);
request.send();
Your best bet is to use the drive_v2_api_client.
This can be done by setting up your google console apis with the following settings for localhost testing with DartEditor
Redirect URIs: http://127.0.0.1:3030/oauth2callback
JavaScript origins: http://127.0.0.1:3030
Then use the dart drive package drive_v2_api_client by putting the following depenencies in your pubspec.yaml file.
dependencies:
drive_v2_api_client:
git: git://github.com/Scarygami/dart_drive_v2_api_client.git
This example allows the client to get the fileid after the client has authenticated with the client id.
import 'dart:html';
import 'dart:json';
import "package:drive_v2_api_client/drive_v2_api_client.dart" as drivelib;
import "package:google_oauth2_client/google_oauth2_client.dart";
final CLIENT_ID = "<YOUR CLIENT ID FROM CONSOLE API>";
final SCOPES = [drivelib.Drive.DRIVE_FILE_SCOPE];
void main() {
var fileid = "1B_cGCNFjnK3dDriTMLsSS_zExfGFkQeewb3dcP4xSPg";
var auth = new OAuth2(CLIENT_ID, SCOPES);
var drive = new drivelib.Drive(auth);
drive.makeAuthRequests = true;
var loginButton = query("#login");
var output = query("#text");
loginButton.on.click.add((Event e) {
auth.login().then((token) {
output.appendHtml("Got Token ${token.type} ${token.data}<br><br>");
drive.files.get(fileid)
..then((data) {
output.appendHtml(data.toString());
});
});
});
}
You can find all the source code to a working example here https://gist.github.com/4588427

How to parse a XML string in a Firefox addon using Add-on SDK

I am trying to create a FF AddOn that brings some XML data from a website. But I can't find a way to parse my RESPONSE. First I used DOMParser but I get this error:
ReferenceError: DOMParser is not defined.
Someone suggested to use XMLHttpRequest, because the parsing is done automatically but then I get this other error:
Error: An exception occurred. Traceback (most recent call last):
File
"resource://jid0-a23vmnhgidl8wlymvolsst4ca98-at-jetpack/api-utils/lib/cuddlefish.js",
line 208, in require
let module, manifest = this.manifest[base], requirer = this.modules[base]; TypeError: this.manifest is undefined
I really don't know what else to do. I must note that I am using the AddOn Builder to achieve this.
Below the code that doesn't seem to work.
Option 1:
exports.main = function() {
require("widget").Widget({
id: "widgetID1",
label: "My Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
var Request = require("request").Request;
var goblecontent = Request({
url: "http://www.myexperiment.org/search.xml?query=goble",
onComplete: function (response) {
var parser = new DOMParser();
var xml = parser.parseFromString(response.text, "application/xml");
var packs = xml.getElementsByTagName("packs");
console.log(packs);
}
});
goblecontent.get();
}
});
};
Option 2:
exports.main = function() {
require("widget").Widget({
id: "widgetID1",
label: "My Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
var request = new require("xhr").XMLHttpRequest();
request.open("GET", "http://www.myexperiment.org/search.xml?query=goble", false);
request.send(null);
if (request.status === 200) {
console.log(request.responseText);
}
}
});
};
DOMParser constructor isn't defined in the context of SDK modules. You can still get it using chrome authority however:
var {Cc, Ci} = require("chrome");
var parser = Cc["#mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
nsIDOMParser documentation.
That said, your approach with XMLHttpRequest should work as well. You used the new operator incorrectly however, the way you wrote it a new "require object" is being created. This way it should work however:
var {XMLHttpRequest} = require("xhr");
var request = new XMLHttpRequest();
Please consider using an asynchronous XMLHttpRequest object however, use request.onreadystatechange to attach your listener (the xhr module currently doesn't support other types of listeners or addEventListener).
If you use XMLHttpRequest (available via the xhr module) you can easily avoid the use of DOMParser. Bellow I provide an example supposing request is an XMLHttpRequest object which request is successfully completed:
Instead of:
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(request.responseText, "application/xml");
Use:
var xmlDoc = request.responseXML;
An then you can:
var packs = xmlDoc.getElementsByTagName("packs");
console.log(packs);
Or whatever.

Resources