Detecting changes of variables' values

Is it possible to detect (and create a trigger for) an event when any of the variables defined in the notebook changes its value (for any reason)?

I need to know which variable got changed and what the new value is.

Here are some details:

I have a client-server application, where the client is my Mathematica notebook. I also have a Java layer in between. The server runs MongoDB database and when any client modifies it, the server sends updates to all other clients. Specifically, to the Java layer. The job of the Java layer is to keep an up-to-date local copy of the database, and to relay all updates to the Mathematica client.


Needs["JLink"]
InstallJava[];
ReinstallJava[ClassPath -> "/Users/verse/Desktop/java-ddp-client.jar"];

url = "localhost"; port = 3000;
client = JavaNew["me.kutrumbos.DdpClient", url,
MakeJavaObject[port]];
observer =
JavaNew["me.kutrumbos.examples.ObservableDdpClientObserver"];
collections = {};
onCollectionUpdate[msg_] :=
Module[{}, collections = observer@getJSONObjectsList["test"];];

ImplementJavaInterface["me.kutrumbos.examples.MessageHandler",
"update" -> "onCollectionUpdate"]];

(ShowJavaConsole[];)
client@connect[];


In this example, variable collections gets updated by the Java layer every time there is a change in the underlying database. It does not happen through the Set command inside the notebook. I need to know when this does happen and I need to properly update other variables.

Conversely, when any of the relevant variables change inside the notebook, I need to be able to update the database on the server using an API request. To send such a request, I need to know which variable has changed and what the new value is.

-
See the help for Dynamic there are many examples there. –  bill s Feb 7 '14 at 15:59
have you seen Monitor[]? –  belisarius Feb 7 '14 at 15:59
@bill s, would you mind pointing me to the part that you had in mind? I've read the Dynamic tutorial, but didn't see a way to detect the changes. My understanding was that Dynamic does the updating itself, but does not allow for trigger actions. @belisarius, I think Monitor won't work for my purposes -- it only shows the current value of a variable while a given expression is evaluated, but in my case there is no evaluation. Variables may be changed at any time by an external process (server update). –  verse Feb 7 '14 at 16:08
Can you be clearer about what you want to happen? Present a specific scenario (preferably with code) so that we can see what you are trying to do? –  bill s Feb 7 '14 at 16:15
@user6236 I have marked this question as too broad, because it is not clear what you are trying to do. Because of the way that Dynamic is implemented it may be useful or entirely useless for your task. There are other methods such as ScheduledTask that you should look at too. But outlining all of these methods is IMHO too extensive. –  Mr.Wizard Feb 7 '14 at 16:31

Something along the lines of ...

a /: Set[a,x_]:=((OwnValues[a]={HoldPattern[a]:>x}; Print[{"a was set to:",x}]); a)

a = 1 prints {a was set to:,1}

a on its own is now 1.


Extends what set does with an additional action which here is Print but ,in principle, could be anything.

-
Be aware that this definition will not catch many of the ways that the value of a can change. I shall wait to see what the OP intends before voting on this. –  Mr.Wizard Feb 7 '14 at 16:29
Unfortunately in my case this method won't work because the variables are updated by the Java layer, and not by the Set command. –  verse Feb 7 '14 at 16:33
@user6236 I see the question has changed quite a bit since it was first posted. How soon after the collection has changed do you need to trigger your process? (emphasis on "need"). –  Ymareth Feb 7 '14 at 16:43
@Ymareth I basically need to have consistently synchronized data across all clients and the server. This requires reacting to all the changes as quickly as possible. –  verse Feb 7 '14 at 16:48
If anybody is willing to investigate or reverse engineer this, take a look at InternalHandlers[], and see "ValueChange"-related ones are useful. I never dug into this and I don't even know if it works or not. –  Szabolcs Feb 7 '14 at 19:36

There is ValueFunction, documented here.

It allows detecting value changes for given symbols.

For example,

In[1]:= ExperimentalValueFunction[x] := Print["x changed"]

In[2]:= x = 6

During evaluation of In[10]:= x changed

Out[2]= 6

-
Why doesn't this have any votes!? +1! –  Mr.Wizard May 11 '14 at 17:49
From the docs: "ValueFunction takes account of all ways that the value of a symbol can be changed, not just Set." However, even a cursory examination shows that this is totally wrong. So much for "documentation"! –  Oleksandr R. May 11 '14 at 20:09
@OleksandrR. How did you break it? –  Szabolcs May 11 '14 at 21:51
Well, it failed with pretty much everything I tried. It seems only to pay attention to OwnValues. Yet, changing even these by any slightly non-standard method (e.g. manipulating OwnValues directly) doesn't trigger it. Nor does changing a part of a value. It would be interesting to know what scenarios it does actually cover. –  Oleksandr R. May 11 '14 at 22:01
@Oleksandr I'm not surprised that direct modification of OwnValues doesn't work, at that is expressly outside of "normal" operation. Things like Increment and AppendTo` do work, but I am sad to see that as you say assignments to parts do not. Nevertheless I think this still has value. –  Mr.Wizard May 12 '14 at 16:20