[OpenLayers-Dev] Possible bug with Protocol.HTTP

Stephen Woodbridge woodbri at swoodbridge.com
Tue May 4 00:16:50 EDT 2010


Eric Lemoine wrote:
> On Sunday, May 2, 2010, Stephen Woodbridge <woodbri at swoodbridge.com>
> wrote:
>> Hi Devs,
>> 
>> I have been working with OL.Protocol.HTTP and I think I have
>> identified a bug in the code after spending considerable time
>> reading and tracing the code via firebug. Basically if you create a
>> Protocol.HTTP with a user callback, it never gets called. Below is
>> a summary of my analysis and I would appreciate it if one of you
>> can confirm or refute these observations.
>> 
>> In OpenLayers.Protocol.HTTP.commit() near the end the code starts 
>> issuing requests with:
>> 
>> var queue = types[OpenLayers.State.INSERT]; if(queue.length > 0) { 
>> resp.push(this.create( queue, OpenLayers.Util.applyDefaults( 
>> {callback: insertCallback, scope: this}, options.create ) )); } 
>> queue = types[OpenLayers.State.UPDATE]; for(var i=queue.length-1;
>> i>=0; --i) { resp.push(this.update( queue[i],
>> OpenLayers.Util.applyDefaults( {callback: callback, scope: this},
>> options.update )) ); } queue = types[OpenLayers.State.DELETE]; 
>> for(var i=queue.length-1; i>=0; --i) { resp.push(this["delete"]( 
>> queue[i], OpenLayers.Util.applyDefaults( {callback: callback,
>> scope: this}, options["delete"] )) ); }
>> 
>> I think the arguments to OpenLayers.Util.applyDefaults(to, from)
>> are reversed in the above code. I think the intent here was to
>> create a hash like:
>> 
>> options[requestType] = {callback: callback, scope: this}
>> 
>> that would get passed as the options array to to the create,
>> update, delete method respectively because this is what is expected
>> later by the OpenLayers.Protocol.HTTP.callUserCallback. Also not
>> the callback() and insertCallback() are local function to commit()
>> and should not be confused with this.callback.
>> 
>> And in fact the above code might be more correctly expressed as for
>> example:
>> 
>> queue = types[OpenLayers.State.DELETE]; for(var i=queue.length-1;
>> i>=0; --i) { var opt = OpenLayers.Util.applyDefaults(options,
>> "delete: {callback: callback, scope: this}); 
>> resp.push(this["delete"](queue[i], opt) ); }
>> 
>> It would seem, this would more accurately reflect the usage below
>> in callUserCallback():
>> 
>> callUserCallback: function(resp, options) { var opt =
>> options[resp.requestType]; if(opt && opt.callback) { 
>> opt.callback.call(opt.scope, resp); } },
>> 
>> In current code (OL 2.8 and OL 2.9) opt is currently always
>> undefined so the callback never gets called.

Hi Eric,

First off, thank you for your responses and help with this issue. The
most important part is that I have code working and doing what I want,
but I had to modify Protocol.HTTP and my server code to get it working.
Eventually I would like to get it to work without modified OL code, but
other work is higher priority at the moment. Given that this was not
trivial and I think there might be some bugs in the code, I am
continuing this thread with the hope of a) learning something and/or b)
giving something back to make the code better if I can.

> 
> I think this is expected.
> 
> For the "commit" operation multiple callbacks come into play. The
> main callback, called when the full commit operation completes, is
> set in the "callback" option. Sub-operation callbacks can also be
> set.
> 
> If you had one or more of these sub-operation callbacks set you'd see
>  them being called in callUserCallback when committing (i.e. calling 
> protocol.commit()).
> 
> To set sub-operation callbacks you'd use something like the following
>  in the options:
> 
> 
> "create": { "callback": function() { alert("create"); } }, "update":
> { "callback": function() { alert("update"); } }, "delete": { 
> "callback": function() { alert("delete"); } }

Right, this is my read on the code, BUT you can not do this when you
initialize the Protocol.HTTP object, because these will over write the
functions of the same name in the class, you have to initialize the
object then extend:

    OpenLayers.Protocol.HTTP.options

in theory, but I could not get these to be invoked in my code either.

Also, looking at the docs the sub-operation callbacks above might only
be valid if passed in the options object to the commit method, but I
have not re-read the code on this point.

I fully admit that it is likely that I do not understand how to use the
code correctly, but it is not from lack of trying and spending a bunch
of time off and on this problem over the last month.

>> A simple test of this is to create an OpenLayers.Protocol.HTTP with
>> a
>> 
>> callback: function() {alert( "Hello World!"); }
>> 
>> and issue a create, update, or delete request via the protocol and
>> the callback is not currently called.
> 
> The callback function should get called here. I'd be interested in a 
> example showing this doesn't work.

Here is a simple example based on the examples/sundials.html where I
just added the callback to that and it is not called.

http://imaptools.com:8080/ol29/examples/sundials2.html

             var sundials = new OpenLayers.Layer.Vector("KML", {
                 projection: map.displayProjection,
                 strategies: [new OpenLayers.Strategy.Fixed()],
                 protocol: new OpenLayers.Protocol.HTTP({
                     url: "kml/sundials.kml",
                     format: new OpenLayers.Format.KML({
                         extractStyles: true,
                         extractAttributes: true
                     }),
                     callback: function(){ alert("Hello!"); } // <<<<<<<<
                 })
             });

Maybe this is a bad example and callback is not invoked on read requests
which is the only request in this example, but there is not much
documentation on how or when the callback is supposed to be used.

All the best,
   -Steve



More information about the Dev mailing list