applyEdits fails in ArcGIS JSAPI - arcgis-js-api

I am using a feature layer in JSAPI, where I edit a feature by the standard selection, change attributes, applyEdits process. It seems that there is a bug in JSAPI both 3.12 and 3.14 which makes the apply edits fail on certain features. The callback just errors out without any clue.
The interesting observations:
Failure only happens on certain features and all cases belong to a particular layer (other features in that layer are just fine).
Changing from 3.12 to 3.14 the features that cause the error are changed but did not go away.
Here is a quick snippet of the code:
sq = buildSelectionQuery();
if (sq) {
all(assetsFeatureLayers.map(function (l) { return l.selectFeatures(sq, esri.layers.FeatureLayer.SELECTION_NEW).promise;})
).then(function (fls) {
console.log('sel res', fls);
all(fls.map(function (r, i) {
var fs = r[0]; // the first is an array of selected features
var l = assetsFeatureLayers[i];
console.log(fs);
if (fs.length > 0) {
console.log("Switching phases to: ", tph);
fs.forEach(function (f) {
f.attributes['phasecode'] = tph;
});
console.log("Saving switched phases for layer: ", l.name);
return l.applyEdits(null, fs, null); //.promise;
} else {
return null;
}
})).then(function (l) {
console.log("Phase switching finished successfully!", l);
clearAllSelections();
}, function (e) {
console.log("Error switching phases!", e);
clearAllSelections();
});
});
}

OK, I found the root cause. We are using ESRI's PHP proxy, and it was a bug in that. Upgrading to the latest 1.1 beta solved the issue. Here is the link to their repo: https://github.com/Esri/resource-proxy

Related

Why is the value not entering the list?

At 'urichecking2' log, I can see there is value. But in 'uriChecking' the uriList is null.
why the uriList.add not work??
private fun getPhotoList() {
val fileName = intent.getStringExtra("fileName")
Log.d("fileNameChecking", "$fileName")
val listRef = FirebaseStorage.getInstance().reference.child("image").child(fileName!!)
var tmpUrl:Uri = Uri.parse(fileName)
Log.d("firstTmpUri","$tmpUrl")
listRef.listAll()
.addOnSuccessListener { listResult ->
for (item in listResult.items) {
item.downloadUrl.addOnCompleteListener { task ->
if (task.isSuccessful) {
tmpUrl = task.result
Log.d("secondTmpUri","$tmpUrl")
Log.d("urichecking2","$task.result")
uriList.add(task.result)
} else {
}
}.addOnFailureListener {
// Uh-oh, an error occurred!
}
}
}
Log.d("thirdTmpUri","$tmpUrl")
Log.d("urichecking", "$uriList")
}
If I do this, the log is output in the order of first, third, and second, and the desired value is in second, but when third comes out, it returns to the value of first.
The listAll method (like most cloud APIs these days, including downloadUrl which you also use) is asynchronous, since it needs to make a call to the server - which may take time. This means the code executes in a different order than you may expect, which is easiest to see if you add some logging:
Log.d("Firebase","Before starting listAll")
listRef.listAll()
.addOnSuccessListener { listResult ->
Log.d("Firebase","Got listResult")
}
Log.d("Firebase","After starting listAll")
When you run this code it outputs:
Before starting listAll
After starting listAll
Got listResult
This is probably not the order you expected, but it perfectly explains why you can't see the list result. By the time your Log.d("urichecking", "$uriList") runs, none of the uriList.add(task.result) has been called yet.
The solution for this is always the same: any code that needs the list result, has to be inside the addOnCompleteListener callback, be called from there, or be otherwise synchronized.
So in its simplest way:
listRef.listAll()
.addOnSuccessListener { listResult ->
for (item in listResult.items) {
item.downloadUrl.addOnCompleteListener { task ->
if (task.isSuccessful) {
uriList.add(task.result)
Log.d("urichecking", "$uriList")
}
}
}
}
This is an incredibly common mistake to make if you're new to programming with asynchronous APIs, so I recommend checking out
Asynchronous programming techniques in the Kotlin language guide
How to get URL from Firebase Storage getDownloadURL
Can someone help me with logic of the firebase on success listener
Why does my function that calls an API or launches a coroutine return an empty or null value?

Intercept XMLHttpRequest from Greasemonkey script fails

I seek to manipulate the XMLHttpRequest done by a website using Greasemonkey (version 4.9 installed). Interception should be simple (How can I intercept XMLHttpRequests from a Greasemonkey script?) but does not work for me. Maybe things changed with newer versions of Greasemonkey?
I obviously tried the examples in the linked question, but they don't have any effect - nothing printed in the console although I have an console.log(...) in my customised open function.
Next, I gave unsafeWindow a try. It should not be needed. My userscript runs with #grant none and documentation (see here) says my script should run in the content scope.
With unsafeWindow I get an effect but it breaks XMLHttpRequest completely
// ==UserScript==
// #name Test
// #version 1
// #include *
// #run-at document-start
// #grant none
// ==/UserScript==
"use strict";
let realOpen = unsafeWindow.XMLHttpRequest.prototype.open
console.log("Real: " + realOpen)
unsafeWindow.XMLHttpRequest.prototype.open = function() {
console.log("Called for " + this + " with URL: " + arguments[0])
//call original
return realOpen.apply(this, arguments)
};
window.addEventListener ("load", function() {
console.log ("Page loaded");
});
console.log("Unsafe: ", unsafeWindow.XMLHttpRequest.prototype.open.toString())
console.log("Normal: ", XMLHttpRequest.prototype.open.toString())
This gives following output in console:
Real: function open() {
[native code]
}
Unsafe: function() {
console.log("Called for " + this + " with URL: " + arguments[0])
//call original
return realOpen.apply(this, arguments)
}
Normal: function open(method, url) {
// only include method and url parameters so the function length is set properly
if (arguments.length >= 2) {
let newUrl = new URL(arguments[1], document.location.href);
arguments[1] = newUrl.toString();
}
return origOpen.apply(this, arguments);
}
==> Page loaded
As mentioned, function of XMLHttpRequest is broken. When I use the Firefox developer console to have a further look I get this
>> window.XMLHttpRequest.prototype.open
Restricted { }
Any properties set on window (like window.foobar = "foobar") do not exist in console, but those set on unsafeWindow do. I assume this has to do with Greasemonkey's sandboxing.
Why are there two versions of XMLHttpRequest even when I use #grant none? Why is my custom function restricted? Can I avoid that? Why does it work without problems when I install event listener on window?
Next, I gave unsafeWindow a try. It should not be needed. My userscript runs with #grant none and documentation (see here) says my script should run in the content scope.
This is wrong for Greasemonkey 4 as stated in its announcement:
Due to the more limited abilities that the new extension system gives us, we are currently unable to make #grant none scripts work in the same way. Most importantly, they have a different connection to unsafeWindow. For the short term at least, it's a good idea to adopt cloneInto and exportFunction.
See also this other question Firefox doesn't respect Object.defineProperty() from a Greasemonkey script?
This change explain the observations, but no idea why adding listener to window work.

janusGraph using remote connection to update and delete : report DefaultGraphTraversal.none()

using janusGraph git code example : example-remotegraph
It works well when i going to create elements and do some query things.
But it report exception when update and delete...
java.util.concurrent.CompletionException: org.apache.tinkerpop.gremlin.driver.exception.ResponseException: Could not locate method: DefaultGraphTraversal.none()
at java.util.concurrent.CompletableFuture.reportJoin(CompletableFuture.java:375)
at java.util.concurrent.CompletableFuture.join(CompletableFuture.java:1934)
at org.apache.tinkerpop.gremlin.driver.ResultSet.one(ResultSet.java:107)
at org.apache.tinkerpop.gremlin.driver.ResultSet$1.hasNext(ResultSet.java:159)
at org.apache.tinkerpop.gremlin.driver.ResultSet$1.next(ResultSet.java:166)
at org.apache.tinkerpop.gremlin.driver.ResultSet$1.next(ResultSet.java:153)
at org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversal$TraverserIterator.next(DriverRemoteTraversal.java:142)
at org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversal$TraverserIterator.next(DriverRemoteTraversal.java:127)
at org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversal.nextTraverser(DriverRemoteTraversal.java:108)
at org.apache.tinkerpop.gremlin.process.remote.traversal.step.map.RemoteStep.processNextStart(RemoteStep.java:80)
at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.next(AbstractStep.java:128)
at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.next(AbstractStep.java:38)
at org.apache.tinkerpop.gremlin.process.traversal.Traversal.iterate(Traversal.java:203)
at org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal.iterate(GraphTraversal.java:2694)
at org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal$Admin.iterate(GraphTraversal.java:178)
at org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal.iterate(DefaultGraphTraversal.java:48)
at org.janusgraph.example.GraphApp.deleteElements(GraphApp.java:301)
at org.janusgraph.example.GraphApp.runApp(GraphApp.java:350)
at org.janusgraph.example.RemoteGraphApp.main(RemoteGraphApp.java:227)
here is the code :
public void deleteElements() {
try {
if (g == null) {
return;
}
LOGGER.info("deleting elements");
// note that this will succeed whether or not pluto exists
g.V().has("name", "pluto").drop().iterate();
if (supportsTransactions) {
g.tx().commit();
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
if (supportsTransactions) {
g.tx().rollback();
}
}
}
emmm.....i thought i have fixed this problem.....
the only reason perhaps the library version used doesn't match the gremlin-server's version;
I tried to turn the gremlin driver library to 3.2.9 version, and it works well.
You need to use the same Tinkerpop version JanusGraph is using, as this is an incompatible change that was introduced in Tinkerpop

How to write custom messages on passed tests with jasmine and protractor?

I'm looking a way to add custom messages on succeeded tests with protractor and jasmine.
There're many ways to customize messages on failure, like jasmine-custom-message node package or simply:
expect(column.get(0)).toEqual("7", "This is not something I've expected");
But I haven't found a way to add custom messages on success. I'm using protractor-jasmine2-html-reporter to generate my reports, but successful tests only display a "passed" or "0 failure" messages and I'd like to be more explicit about what am I testing and why the tests passed.
You want to write a custom matcher for Jasmine. You want to include them in the protractor.conf.js file so they are accessible over the entire project
https://jasmine.github.io/2.0/custom_matcher.html
Here is an example of comparing numbers with the message printing off if there is an error. The error if you run this will be Expected 7 to be 8 (Expected Error). Note, this is including it in the spec using the beforeEach.
var customMatchers = {
toBeEqualWithMessage: function(util, customEqualityTesters) {
return {
compare: function(actual, expected, message) {
var result = {};
result.pass = util.equals(actual, expected, customEqualityTesters);
if (!result.pass) {
result.message = "Expected " + actual + " to be " + expected + " (" + message + ")";
}
return result;
}
};
}
};
describe('Custom Matcher', function(){
beforeEach(function() { jasmine.addMatchers(customMatchers);});
it('should use a matcher', function(){
expect(7).toBeEqualWithMessage(7,"No error because they match");
expect(7).not.toBeEqualWithMessage(8,"No error because of the 'not'");
expect(7).toBeEqualWithMessage(8,"Expected Error");
});
});
FYI: The doc has a result.message for a passing case, but I don't know where that is used, maybe a verbose print out.

hand tracking not working after a reload of openni dynamic library

Our project is (http://www.play4health.com/p4h_eng/) using Ogre 3D
over Ubuntu 11.04. Except for core services all is based in a plugin architecture taking advantage of Ogre 3d plugin facilities.
In our plugin architecture plugins can be:
Videogames
Interaction methods
Users configure their session creating tuples (videogame, interaction
method). The flow is a session is:
* User load his session.
* User click of one of the tuples for the session and play to
videogame with a specific interaction method.
* Repeat it until end all activities of the session.
Plugin are loaded/unloaded dynamically by demand.
One of this interaction methods is hand tracking using openni. What is
the problem?
* Fist time that openni plugin is loading all work perfectly.
* Next time that plugin openni has to be loaded system is able to
detect gestures but not do hand tracking. Note that all plugin are
executed in the same process. Right now only solution is to reboot
platform.
This is the code for init and release OpenNI in our plugin
bool IPKinectPlugin::onInitialise()
{
mHandPointer.mId = "KinectHandPointer";
mHandPointer.mHasAbsolute = true;
mHandPointer.mHasRelative = false;
XnStatus nRetVal = XN_STATUS_OK;
nRetVal = gContext.InitFromXmlFile(String(this->getPluginInfo()-
>getResPath() + "SamplesConfig.xml").c_str());
CHECK_RC(nRetVal, bContext, "InitFromXml");
#if SHOW_DEPTH
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_DEPTH,gDepthGenerator);
bDepthGenerator = (nRetVal != XN_STATUS_OK);
if (bDepthGenerator)
{
nRetVal = gDepthGenerator.Create(gContext);
CHECK_RC(nRetVal, bDepthGenerator, "Find Depth generator");
}
#endif
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_USER, gUserGenerator);
bUserGenerator = (nRetVal != XN_STATUS_OK);
if (/*bUserGenerator*/false)
{
nRetVal = gUserGenerator.Create(gContext);
CHECK_RC(nRetVal, bUserGenerator, "Find user generator");
}
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_GESTURE, gGestureGenerator);
bGestureGenerator = (nRetVal != XN_STATUS_OK);
if (bGestureGenerator)
{
nRetVal = gGestureGenerator.Create(gContext);
CHECK_RC(nRetVal, bGestureGenerator, "Find gesture generator");
XnCallbackHandle hGestureCallbacks;
gGestureGenerator.RegisterGestureCallbacks(gestureRecognized, gestureProcess, 0,
hGestureCallbacks);
}
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_HANDS,gHandsGenerator);
bHandsGenerator = (nRetVal != XN_STATUS_OK);
if (bHandsGenerator)
{
nRetVal = gHandsGenerator.Create(gContext);
CHECK_RC(nRetVal, bHandsGenerator, "Find hands generator");
XnCallbackHandle hHandsCallbacks;
gHandsGenerator.RegisterHandCallbacks(handsNew, handsMove,handsLost, 0, hHandsCallbacks);
}
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_DEVICE, gDevice);
bDevice = (nRetVal != XN_STATUS_OK);
gContext.RegisterToErrorStateChange(onErrorStateChanged, NULL, hDummyCallbackHandle);
//Preparo la textura para la webcam
if (bGenerateRGBTexture)
mWebcamTexture = KinectTools::createDepthTexture("KinectWebCamTexture", sPluginName);
return true;
}
//-----------------------------------------------------------------------------
bool IPKinectPlugin::onShutdown()
{
if (bContext)
{
if (bHandsGenerator)
{
gHandsGenerator.StopTrackingAll();
}
if (bGestureGenerator)
{
gGestureGenerator.RemoveGesture(GESTURE_TO_USE);
gGestureGenerator.RemoveGesture(GESTURE_TO_START);
}
gContext.StopGeneratingAll();
gContext.Shutdown();
}
return true;
}
Any idea about this issue? Any wrong with this code?
Maybe you already found a solution in the meantime...
I normally work with the Java Wrapper, but what I see as difference to my code is that I call contect.startGeneratingAll() after creating the generators (Depth, Hands and so on). I had also problems when I did this multiple times at start up. Another difference is that I use a context.release at shutdown.
My procedure is normally:
Init config (License, Nodes, settings)
Create generators
Start Generating All
Run your code ...
Stop Generating ALL
Context release
From OpenNI Documentation
XN_C_API void XN_C_DECL xnShutdown ( XnContext * pContext )
Shuts down an OpenNI context, destroying all its nodes. Do not call
any function of this context or any correlated node after calling this
method. NOTE: this function destroys the context and all the nodes it
holds and so should be used very carefully. Normally you should just
call xnContextRelease()