Uploaded image for project: 'Spring Data GemFire'
  1. Spring Data GemFire
  2. SGF-55

Consider providing support for executing code dynamically on GemFire

    XMLWordPrintable

    Details

      Description

      I came up with a means of executing code dynamically across Gemfire servers and regions. The idea was motivated by wanting to retain the separation of concerns between an application's logic layer and its data layer (Gemfire). I felt that the logic layer should be able to deliver code to execute to the data layer, rather than the data layer have to be distributed (built) with that logic layer code.

      I put together a Function subclass that allows JavaScript code to be passed to Gemfire and then executed as per any other Function object. The JavaScript is able access anything on the classpath and is thus very flexible.

      I have attached a patch file that you might find suitable for inclusion in Spring Gemfire. The patch includes an enhancement to GemfireTemplate to execute JavaScript conveniently and new JSExecutor and JSExecutorArgs classes. In addition I have included documentation and unit tests for JSExecutor and GemfireTemplate.

      I've found the execution of JavaScript particularly useful in my DAOs. Here is an example using an extension I've made to GemfireTemplate in a small application I am writing:

      @SuppressWarnings("unchecked")
      public List<User> getFollowers(String handle) {
          @SuppressWarnings("rawtypes")
          List<ArrayList> results = getGemfireTemplate().executeJs(
              ArrayList.class, handle, this.getClass().getResourceAsStream("GetFollowers.js"));
          return results.get(0);
      }
      

      The above returns the followers of a user referenced by the variable handle. The GetFollowers.js file is defined as:

      /*global context, args */
      var follower, followerId, followers, iterator, user;
      
      // Get the user associated with our filter. Note that there has to be one or
      // this function would not be called.
      user = context.dataSet.get(context.filter.toArray()[0]);
      
      // For each follower id in the user obtain the associated user object and it to
      // our list.
      followers = new java.util.ArrayList(user.followers.size());
      iterator = user.followers.iterator();
      while (iterator.hasNext()) {
          followerId = iterator.next();
          follower = context.dataSet.get(followerId);
          followers.add(follower);
      }
      
      // Return the list of followers.
      followers;
      

      The only problem I've ran into so far is that I do not appear to be able to execute a function in the context of a transaction. I get a com.gemstone.gemfire.InternalGemFireError: dm not in initMembers.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              dturanski David Turanski
              Reporter:
              huntc Christopher Hunt
              Last updater:
              John Blum John Blum
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: