4 Replies Latest reply on Mar 17, 2009 6:17 AM by tom.baeyens

    programmatic passing of environment objects

    tom.baeyens

      there are some situations where we need to support passing of environment objects into the service method invocations:

      * user provided JDBC connection
      * user provided hibernate session
      * programmatic specification of the current authenticated user

      Of coure, we should not add those as optional parameters to all our service method invocations.

      One solution I thought of was something like this:

      /** the {@link TaskService task service} that exposes the
       * runtime human task lists. */
       TaskService getTaskService();
      
       /** the {@link TaskService task service} and supply some
       * transactional resources. The given transactional resources will only
       * be associated to the returned task service. */
       TaskService getTaskService(Map<String, Object> envObjects);
      


      that way, environment objects could be passed in to the service objects. TaskServices that are created with the second method would typically be used for only one invocation as transactional resources are passed into it.

      Still trying to figure out how we can cleanly handle typed objects... When the engine e.g. gets the Authentication with Environment.getFromCurrent(Authentication.class) then we should be able to do something like:

      Map<String, Object> envObjects = new HashMap<String, Object>();
      envObjects.put("authentication", new UserProvidedAuthentication("johndoe"));
      TaskService taskService = processEngine.getTaskService(envObjects);
      taskService.take(taskdbid);


        • 1. Re: programmatic passing of environment objects
          heiko.braun

          Callbacks would be another possibility. Clients would need to provide an implementation of that callback interface:


          TaskService getTaskService(CallbackInterface callback);
          


          So, instead of 'pushing' the information into the service, the service would 'callbacl' the client environment when needed.

          • 2. Re: programmatic passing of environment objects
            tom.baeyens

            maybe this is better:

            TaskService taskService = processEngine.getTaskService();
            
            
            try {
             Authentication authentication = new UserProvidedAuthentication("johndoe");
             taskService.setEnvironmentObject(authentication);
            
             taskService.take(taskdbid);
            
            } finally {
             taskService.removeEnvironmentObjects();
            }
            


            or by name

            TaskService taskService = processEngine.getTaskService();
            
            Authentication authentication = new UserProvidedAuthentication("johndoe");
            taskService.setEnvironmentObject("authentication", authentication);
            
            taskService.take(taskdbid);
            



            • 3. Re: programmatic passing of environment objects
              heiko.braun

              You can skip the 'finally' when using the callback because it's managed outside of the task service:

              [...]
               finally {
               taskService.removeEnvironmentObjects();
              }
              



              Same applies to the lookup key. Using a callback would force the task service to engage the lookup with it's key and not the client environment.

              taskService.setEnvironmentObject("authentication", authentication);
              


              • 4. Re: programmatic passing of environment objects
                tom.baeyens

                 

                "heiko.braun@jboss.com" wrote:
                You can skip the 'finally' when using the callback because it's managed outside of the task service:


                i don't think so. if the services remain process-engine-context scoped objects, then the callback object would have to be removed just like the provided objects themselves... i think.

                internally we only have 1 option:

                use a thread local to pass these objects down till the environment is created. in that case the services can remain process-engine-context scoped. if we use thread locals to pass the user provided objects or the callback handlers, that thread local cleanup is also needed for callback handlers.


                another alternative would be to create a new service object for each request. but then we would not be able to configure the services. users will not be able to configure customized services. maybe that is an other option to consider. but i don't yet see the full implications of that. feels scary to go that route