Hi all,
Before you get reading what is maybe a tl;dr… I should say this isn’t asking a question or raising a problem, but is just a discussion/interest point related to java snippets!
For some of you, what I am writing here won’t come as a surprise, but I thought it worth writing as it might avoid the mistake I made, and it also can potentially be quite useful.
While playing with Java snippets I was surprised to stumble on some interesting behaviour. I had “incorrectly” initialised the variables and not really considered how Java Snippets are implemented so at first I was surprised, but after playing with them for a few minutes, the reason for the behaviour made sense.
It was, however, what I would term a “gotcha”. We are generally given to believe that a java snippet acts only on the data from the single row that is presented to it, and so data from other rows cannot be accessed. Well this is still true, we cannot directly reference other rows, but that is not to say that a java snippet cannot be coded to be presented with data acquired from other (earlier) rows…
Let me explain what I am talking about by way of an example.
Here is some sample data in a Table Creator:
and here is a small java snippet:
What would you expect the result of the output “Message” column to be for each of these rows? (The code is relatively simple so hopefully you can take a guess, even if you don’t know java)
Taken literally, you might think that the “message” variable gets set to " is a girl", and then, if the “Sex” column on a given row is “Male”, the message gets changed to " is a boy", so (for our sample data) the resulting output would be alternating phrases of “[name] is a boy”, and “[name] is a girl”
Something like this perhaps?
Except this would be wrong. The resulting output from the above java snippet is this:
Did that come as a surprise? It did to me. You may be thinking, as I did…“How can that be when the girls are clearly marked as “Female” (i.e. not “Male”) in the Sex column?”
Well, the correct snippet to produce the expected behaviour is this:
This is because the section marked “Your custom variables” is (I am guessing) only processed during the instantiation (the creation) of the object built from this piece of java. If you ever wondered why that section is split away, now you know (at least one of) the reasons. They are “Global” variables and so the variables created there are not re-initialised for each row. Hence when “message” gets set to " is a boy" on the first row, it remains as " is a boy" for the processing of every other row, as nothing changes it.
This got me thinking that whilst this could lead to unexpected consequences if care is not taken to correctly initialise variables for each invocation of the snippet, they could actually have some quite beneficial consequences that I hadn’t previously realised was possible with this node.
Since beginning to write this post, I have re-read the help for “Java Snippet”, I see now that it does say : Note that the snippet allows defining custom global variables I hadn’t read that bit before, and in my defence, I don’t think it is obvious in the snippet dialog that “Your custom variables” actually means “Your custom global variables”. Maybe that should be made clearer for people like me! I had previously just been putting all my variable declarations in that section without giving it a second thought!
So, now that we have this information, what can we do with it?
For example, how about calculating a running total (cumulative sum)…
Or a java snippet “lag column”
Or some sort of “progressive concatenation” of names…
A sequence generation within a some form of grouping:
A “counter generator” (another one!)
So for some (or maybe all) of the above, there are other nodes available that can do the job maybe better, or more efficiently, and these examples are only for demonstration, but they do demonstrate a (not always obvious) side-effect of the implementation of the java snippets which could potentially trip people up, but could also be useful on occasion.
If there is a purpose-built node that can do the job, I would strongly advise using it, rather than writing a java snippet to do it, both for reasons of performance/efficiency and because it’s already been tested, but there might just be a time when this feature could prove useful.
All of the above can be seen demonstrated in the attached workflow.
Java Snippets Have Memory.knwf (18.1 KB)
Hope you all have a great weekend!