Caching and re-using bindings

Edmond Kemokai ekemokai at gmail.com
Thu Dec 8 15:58:46 UTC 2016


Not a problem at all, happy to help!!

Also feel free to further explore HiveMind and share with other devs, it is
a very innovative platform for using Java scripting engines to build webs.

On Dec 8, 2016 9:18 AM, "yikes aroni" <yikesaroni at gmail.com> wrote:

thanks Edmond --- VERY MUCH FOR YOUR TIME!!!!!!!

So i see where i was thinking wrong. And the "workaround" that i've been
using isn't really a workaround at all, but a canonical approach: namely,
if you want to snapshot and cache the engine bindings, you
createBindings(), then putAll of what's in the engine bindings at that
point.

again, thank you. People like you who help (and stick with it even when one
is being thick!) are solid gold.



On Wed, Dec 7, 2016 at 2:51 PM, Edmond Kemokai <ekemokai at gmail.com> wrote:

> Your code is working as expected, I think your understanding of how it
> should work is a bit off. When I look at your code I see you retrieve the
> current engine binding via se.getBindings, this simply returns the binding,
> it doesn't disassociate it with the engine. So when you subsequently define
> new variables they'll still show up in that binding because that binding
> remains associated, ie "bound" to the engine.
>
>
> I added a new version of your code that shows how you can use different
> bindings without them stepping on one anothers toes. Just right-click on
> *binding-test.ste* and choose "*Test In Browser*" to see the result.
> Notices the second variable does not show up in the original binding.
>
> To see the difference in my code, just comment out the line with
> setBindings (and save, then test again), it will behave like your code
> again.
>
>
>
> On Wed, Dec 7, 2016 at 12:51 PM, yikes aroni <yikesaroni at gmail.com> wrote:
>
>> Hi edmond ... I went to your link and added my code but wasn't clear to
>> me what to do from that point. The (java) code is simply this (below).  It
>>
>>
>>    1. adds a variable to ENGINE bindings
>>    2. Creates a "cache" of the ENGINE bindings (variable named "bEngine")
>>    3. Adds another variable to the engine bindings
>>    4. -->  this is what i find unexpected: the new variable appears in
>>    the "cached" bEngine bindings.
>>
>> That's really the nut of it for me: The "copy" of the ENGINE scope
>> bindings appears to be a reference to the actual engine scope bindings, not
>> a copy of them. If i explicitly create a new bindings
>>
>> var bEngine = new SimpleBindings(se.getBindings(ScriptContext.ENGINE));
>>
>> the same thing happens -- any variable added to the engine scope bindings
>> appears in bEngine. I assume this is by design, but i can't understand WHY
>> that would be the design...
>>
>> The workaround i've found is to create a generic map to use as a cache
>> (rather than using getBindings()) and putAll from the engine bindings.
>>
>>
>> import java.util.Map;
>>
>> import javax.script.Bindings;
>> import javax.script.ScriptContext;
>> import javax.script.ScriptEngine;
>> import javax.script.ScriptEngineManager;
>>
>> public class TempEngineTest2 {
>>
>> static ScriptEngineManager seManager = new ScriptEngineManager();
>> static ScriptEngine se = seManager.getEngineByName("nashorn");
>> public static void printBindings(Map<String, Object> bindings) {
>> System.out.println("------------------------");
>> for (Map.Entry<String, Object> entry : bindings.entrySet()) {
>>    System.out.println(entry.getKey() + " = " + entry.getValue());
>> }
>> }
>> public static void main(String[] a) throws Exception {
>> // put variable globalA into the ScriptContext.ENGINE_SCOPE bindings
>> se.eval("globalA = 'testA';");
>> // Snapshot the bindings from the engine.
>> Bindings bEngine = se.getBindings(ScriptContext.ENGINE_SCOPE );
>> // print the bindings to confirm there is only one variable in them. -->
>> TRUE
>> printBindings(bEngine);
>> // put variable globalB into the ScriptContext.ENGINE_SCOPE bindings
>> se.eval("globalB = 'testB';");
>> // print the bindings. Now both variables are present........... WHY???
>> printBindings(bEngine);
>> }
>> }
>>
>> On Tue, Dec 6, 2016 at 8:56 AM, Edmond Kemokai <ekemokai at gmail.com>
>> wrote:
>>
>>> I doubt there is a problem, you're probably making a minor error. I am
>>> the developer of HiveMind, it is a web app platform that relies entirely on
>>> scripting engines. It doesn't cache bindings but rather caches the engine
>>> and creates a new binding to handle every request.
>>>
>>> You can access a demo instance: http://demo.crudzilla.com:7000/
>>> Login with: developer/developer
>>>
>>> I have created a test file in: /com/crudzilla/cloudTest/web/b
>>> inding-test.ste
>>>
>>> Put your code in there and save, I'll take a look to see what might be
>>> missing.
>>>
>>>
>>>
>>>
>>>
>>> On Tue, Dec 6, 2016 at 8:04 AM, yikes aroni <yikesaroni at gmail.com>
>>> wrote:
>>>
>>>> Hmm.... it works if i instantiate the SimpleBinding obj and then putAll
>>>> the bindings from the original bindings obj.
>>>>
>>>> Bindings bSimple = new SimpleBindings();
>>>> bSimple.putAll(bEngine);
>>>>
>>>> Otherwise they either remain the same object or are bound in some way
>>>> s.t. changes to bEngine are in bSimple. This just seems strange to me.
>>>> Still curious to know what the reason for this is, despite having found a
>>>> workaround.
>>>>
>>>>
>>>>
>>>> On Tue, Dec 6, 2016 at 7:59 AM, yikes aroni <yikesaroni at gmail.com>
>>>> wrote:
>>>>
>>>>> Thanks for your response Edmond -- the problem is that a
>>>>> simplebindings object still gets all the changes to the original
>>>>> bindings.... see below:
>>>>>
>>>>> // put variable globalA into the ScriptContext.ENGINE_SCOPE bindings
>>>>> se.eval("globalA = 'testA';");
>>>>> // Snapshot the bindings from the engine.
>>>>> Bindings bEngine = se.getBindings(ScriptContext.ENGINE_SCOPE );
>>>>> // print the bindings to confirm there is only one variable in them.
>>>>> --> TRUE
>>>>> printBindings(bEngine);
>>>>> ------------------------
>>>>> globalA = testA
>>>>> // At this point there is only 'globalA' in the bindings so
>>>>> instantiate simplebindings:
>>>>> Bindings bSimple = new SimpleBindings(bEngine);
>>>>> // Verify by printing the bindings
>>>>> printBindings(bSimple);
>>>>> ------------------------
>>>>> globalA = testA
>>>>> // put variable globalB into the ScriptContext.ENGINE_SCOPE bindings
>>>>> se.eval("globalB = 'testB';");
>>>>> // print the bindings. Now both variables are present........... WHY???
>>>>> printBindings(bEngine);
>>>>> ------------------------
>>>>> globalA = testA
>>>>> globalB = testB
>>>>> // But look -- they are in the simple bindings obj as well!
>>>>> printBindings(bSimple);------------------------
>>>>> globalA = testA
>>>>> globalB = testB
>>>>>
>>>>> That's precisely what i don't get --> Why are variables added to the
>>>>> engine bindings *after* instantiating the simpleBindings showing up in the
>>>>> simpleBindings object?
>>>>>
>>>>> And how do i avoid that?
>>>>>
>>>>> thanks
>>>>>
>>>>> On Mon, Dec 5, 2016 at 3:01 PM, Edmond Kemokai <ekemokai at gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Why don't you create instances of SimpleBinding and use those as
>>>>>> needed? Use ScriptEngine.setBindings to reset the binding...
>>>>>>
>>>>>> On Dec 5, 2016 1:36 PM, "yikes aroni" <yikesaroni at gmail.com> wrote:
>>>>>>
>>>>>>> I want to cache ScriptEngine bindings for reuse. The basic algo
>>>>>>> would be
>>>>>>>
>>>>>>> 1) Build up my ScriptEngine (SE) with stuff i need.
>>>>>>> 2) Snapshot the bindings -- i.e., cache them
>>>>>>> Use engine.getBindings(ScriptContext.ENGINE_SCOPE)
>>>>>>> 3) Use the SE for stuff that might modify its state.
>>>>>>> 4) When done, replace the SE's bindings with my snapshotted bindings
>>>>>>> Use engine.setBindings(_bindings_, ScriptContext.ENGINE_SCOPE)
>>>>>>> 5) I now have a "fresh" SE to use.
>>>>>>>
>>>>>>> The problem is that this doesn't work as expected. The cached
>>>>>>> bindings
>>>>>>> appear to point to the actual SE bindings and therefore whatever
>>>>>>> gets added
>>>>>>> to the SE bindings, also gets added to the cached bindings. Here's
>>>>>>> some
>>>>>>> code to show how it's not doing what i would expect.
>>>>>>>
>>>>>>> public class TempEngineTest {
>>>>>>>
>>>>>>> static ScriptEngineManager seManager = new ScriptEngineManager();
>>>>>>> static ScriptEngine se = seManager.getEngineByName("nashorn");
>>>>>>> public static void printBindings(Map<String, Object> bindings) {
>>>>>>> for (Map.Entry<String, Object> entry : bindings.entrySet()) {
>>>>>>>    System.out.println(entry.getKey() + " = " + entry.getValue());
>>>>>>> }
>>>>>>> }
>>>>>>> public static void main(String[] a) throws Exception {
>>>>>>> // put variable globalA into the ScriptContext.ENGINE_SCOPE bindings
>>>>>>> se.eval("globalA = 'testA';");
>>>>>>> // Snapshot the bindings from the engine.
>>>>>>> Bindings bEngine = se.getBindings(ScriptContext.ENGINE_SCOPE );
>>>>>>> // print the bindings to confirm there is only one variable in them.
>>>>>>> -->
>>>>>>> TRUE
>>>>>>> printBindings(bEngine);
>>>>>>> // put variable globalB into the ScriptContext.ENGINE_SCOPE bindings
>>>>>>> se.eval("globalB = 'testB';");
>>>>>>> // print the bindings. Now both variables are present...........
>>>>>>> WHY???
>>>>>>> printBindings(bEngine);
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> I've seen suggestions to cache and reuse bindings in various
>>>>>>> articles, but
>>>>>>> no specific code for doing so. How do i accomplish this in actual
>>>>>>> code?
>>>>>>>
>>>>>>> thanks
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>>
>>
>
>
>
>


More information about the nashorn-dev mailing list