cancel
Showing results for 
Search instead for 
Did you mean: 

@Autowired in custom renderer - no service exists

udoderk
Champ in-the-making
Champ in-the-making
Hi all,

we need to allow in user task to select the condition, that will be used on condition flow / gateway.

As first step of those realisation with Activiti 5.10 i have created the custom form type/render/validation, registered that in applacationContext /ui-context xml files.
Then i would be set the value for the process variable, that was declared into bpmn xml file, programmaticaly.

I found the possible method

  void setVariable(String executionId, String variableName, Object value);

on RuntimeService. That class is registered as Spring bean as following

  <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
  <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
  <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
  <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
  <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
  <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />

Then i have the used that annotation to inject the runtimeService instance
@Autowired
RuntimeService runtimeService;

Because this method setVariable needs the executionId , i'm used that annotation for processInstance to get the execution id.
@Autowired
   ProcessInstance processInstance;
.

But if i start the business process and see the user task with needed mask, the runtimeService and processInstance are NULL!

What i do wrong???

Can i get the needed instances without sping magic?
9 REPLIES 9

jbarrez
Star Contributor
Star Contributor
The runtimeservice can be autowired, but the process instance not.

But in any case, the runtimservice should not be null. Is the bean you are injecting it in, also defined in Spring? Do you use component scanning (ie is it enabled?)

udoderk
Champ in-the-making
Champ in-the-making
The runtimeservice can be autowired, but the process instance not.

But in any case, the runtimservice should not be null. Is the bean you are injecting it in, also defined in Spring? Do you use component scanning (ie is it enabled?)

Hi jbarrez, now i have noticed that I've posted in the wrong section Smiley Surprisedops:  Smiley Surprisedops:  Smiley Surprisedops: (i would to post on activiti explorer section).
I thank you for pointing to control Spring configuration xml tags: I'm found, that <context:annotation-config /> was missed Smiley Sad  into applicationContext.xml.

Now, after allowing the annotation wiring the runtimeservice is not a null.

Yesterday I found that autowired annotation @Autowired protected ProcessInstance processInstance was used in that example

During cheking of applicationContext.xml i have found that there is no beans named ProcessInstance exist  :cry:

Only with runtimservice i can't change the process variable using setValue method, because this method needs the execution Id.

How retrieve the  execution Id, if the change of the process variables need to be realized inside of UI.Renderer context???

BTW.

(The custom renderer was already registered on formPropertyRendererManager bean as list entry
<bean id="formPropertyRendererManager" class="org.activiti.explorer.ui.form.FormPropertyRendererManager" lazy-init="true">
    <!– Default renderer –>
    <property name="noTypePropertyRenderer">
      <bean class="org.activiti.explorer.ui.form.StringFormPropertyRenderer" />
    </property>
    <!– Renderers by property type –>
    <property name="propertyRenderers">
      <list>
        <bean class="org.activiti.explorer.ui.form.StringFormPropertyRenderer" />

        <bean class="com.myspace.ui.renderer.DoubleFormPropertyRenderer" />

      </list>
    </property>
  </bean>
)

P.S now i know, that i need not process instance id - butexecution id

jbarrez
Star Contributor
Star Contributor
You can't get the process instance injected, that works only for service tasks or expressions.

How retrieve the execution Id, if the change of the process variables need to be realized inside of UI.Renderer context???

That's not necessary, if you hook in the custom renderer, it will automatically be saved to a process variable.

udoderk
Champ in-the-making
Champ in-the-making
You can't get the process instance injected, that works only for service tasks or expressions.

How retrieve the execution Id, if the change of the process variables need to be realized inside of UI.Renderer context???

That's not necessary, if you hook in the custom renderer, it will automatically be saved to a process variable.

Hi jbarrez,

More Details:
: I modified the vacation request  example from activiti demo : "enum" replaced by "true"/"false" values:


…………..
    <exclusiveGateway id="requestApprovedDecision" name="Request approved?" />
    <sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
      <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression>
    </sequenceFlow>
…………
After i deploy the whole vacation request bpmn file,  the 2 checkboxs appears - like following pseudogui
|X| -requestApproved
|..| - requestNotApproved[

If i click on requestNotApproved, so clickEvent  fired and i wish set the value for vacationApproved programatically (a-ka vacationApproved ='false'). This setting method would be called into checkbox click -event-handling of boolean renderer, that i can change too.

To set vacationApproved i would use the RuntimeService.

The RuntimeService has two methods, that have as parameter executionId, that cannot be null!.

I wish to set the value for the process variable. That process variable used on the flow condition, that was declared into bpmn xml file.

The documentation of the setvalue methods.
/** Update or create a variable for an execution.  If the variable is not already existing somewhere in the execution hierarchy,
   * it will be created in the process instance (which is the root execution).
   * @param executionId id of execution to set variable in, cannot be null.
   * @param variableName name of variable to set, cannot be null.
   * @param value value to set. When null is passed, the variable is not removed,
   * only it's value will be set to null.
   * @throws ActivitiException when no execution is found for the given executionId.
   */
  void setVariable(String executionId, String variableName, Object value);

  /** Update or create a variable for an execution (not considering parent scopes).
   * If the variable is not already existing, it will be created in the given execution.
   * @param executionId id of execution to set variable in, cannot be null.
   * @param variableName name of variable to set, cannot be null.
   * @param value value to set. When null is passed, the variable is not removed,
   * only it's value will be set to null.
   * @throws ActivitiException when no execution is found for the given executionId.  */
  void setVariableLocal(String executionId, String variableName, Object value);

Thus imho i need the executionId value

frederikherema1
Star Contributor
Star Contributor
You can use the process instance id as "executionId" value, the process-instance is an execution itself…

udoderk
Champ in-the-making
Champ in-the-making
You can use the process instance id as "executionId" value, the process-instance is an execution itself…
Hi frederikheremans,
Thank you for your prompt reply!

But how do I get process instance id in ui Renderer-Context??

I use the activiti explorer, i'm don't start itself the business process using activiti API

P.S

I could use the process instance id as "executionId" in this case , but if the subprocess would be used, process instance id is not same as executionId":

http://forums.activiti.org/en/viewtopic.php?f=6&t=4291&view=previous

frederikheremans 
Post subject: Re: Question considering process correlation
Posted: Mon Jul 23, 2012 7:56 am

Joined: Thu Aug 26, 2010 6:59 am
Posts: 1595
Location: Aarschot, Belgium 
Use the business-key to correlate between an unique ID and a process-instance. When starting the process, you can pass that in. Afterwards, you can query for the process-instance OR child-executions using executionQuery.processInstanceBusinessKey(…).

A process-instance is indeed an "execution", it's the ROOT execution for a running process. When a process splits into 2 parallel paths or needs a sub-scope (e.g.. subprocess), one or more child-executions are created. These executions reference the process-instance. On a ProcessInstance object, you can get the "process definition id", on an execution, you can't do this directly (can be done using the process-instance-id however). The business-key is a globally UNIQUE identifier YOU can give to a certain process. This key is not used by activiti, this uses the internal ID's. The business-key allows you to lookup a process-instance based on some key your business uses (hence the term).

In case of call-activities, you'll have a process-instance for your main process (game loop) and one for your call-activity. Potentially, there are more executions in between them, depending in the type of process.

Hopes this helps.

http://forums.activiti.org/en/viewtopic.php?f=6&t=4799&start=0
Are executionId and processInstaceId always the same?
jbarrez 
Post subject: Re: Are executionId and processInstaceId always the same?
Posted: Wed Oct 24, 2012 7:05 am

Joined: Sun May 16, 2010 12:14 pm
Posts: 1690
Location: Belgium 
No, depending on the complexity of your process you will have multiple executions (eg for each parallel path, for each scope, ect.) as child of the process instance or even nested.

P.P.S i tried to use the impl class org.activiti.engine.impl.context.Context in my renderer

  try {
   ExecutionContext executionContext = org.activiti.engine.impl.context.Context.getExecutionContext();

   if (executionContext == null) {
    System.out.println("executionContext is NULL");
   } else {
    System.out.println("executionContext is not null");

    ExecutionEntity execution = executionContext.getExecution();
    if (execution == null) {

    } else {
     System.out.println("execution getId " + execution.getId());
     System.out.println("execution getProcessInstanceId  " + execution.getProcessInstanceId());
     System.out.println("execution getProcessDefinitionId  " + execution.getProcessDefinitionId());

    }
   }
  } catch (Exception ex) {
   ex.printStackTrace();
  }

But the EmptyStackException will be thrown.

java.util.EmptyStackException
        at java.util.Stack.peek(Stack.java:102)
        at org.activiti.engine.impl.context.Context.getExecutionContext(Context.java:68)
        at com.tst.activiti.explorer.ui.renderer.MyRenderer.intializeField(MyRenderer.java:42)
        at com.tst.activiti.explorer.ui.renderer.MyRenderer.getPropertyField(MyRenderer.java:110)
        at org.activiti.explorer.ui.form.FormPropertiesComponent.setFormProperties(FormPropertiesComponent.java:69)
        at org.activiti.explorer.ui.form.FormPropertiesForm.setFormProperties(FormPropertiesForm.java:75)
        at org.activiti.explorer.ui.task.TaskDetailPanel.initTaskForm(TaskDetailPanel.java:306)
        at org.activiti.explorer.ui.task.TaskDetailPanel.init(TaskDetailPanel.java:118)
        at org.activiti.explorer.ui.task.TaskDetailPanel.attach(TaskDetailPanel.java:99)
        at com.vaadin.ui.AbstractComponent.setParent(AbstractComponent.java:570)

frederikherema1
Star Contributor
Star Contributor
Now I understand your issue… The form-properties are rendered outside of the activiti-context, so it makes sense the Context throws and EmptyStackEx.

Since the form-properties are also used for start-forms, they are made so generic, that they aren't aware of any process-instance that might be active.

TaskDetailPanel:
protected void initTaskForm() {
    // Check if task requires a form
    TaskFormData formData = formService.getTaskFormData(task.getId());
    if(formData != null && formData.getFormProperties() != null && formData.getFormProperties().size() > 0) {
      taskForm = new FormPropertiesForm();
      taskForm.setSubmitButtonCaption(i18nManager.getMessage(Messages.TASK_COMPLETE));
      taskForm.setCancelButtonCaption(i18nManager.getMessage(Messages.TASK_RESET_FORM));
      taskForm.setFormHelp(i18nManager.getMessage(Messages.TASK_FORM_HELP));
      taskForm.setFormProperties(formData.getFormProperties());

The class org.activiti.explorer.ui.form.FormPropertiesForm only receives the form-properties and no process-context. Your use case makes sense, though. If you want, you could add a processInstanceId and executionId (which may be null) to the render() method of form-properties and make sure it's passed from initiTaskForm() in TaskDetailPanel, al the way down to the actual render call. If you create a pull-request for this, I'm happy to accept it…

udoderk
Champ in-the-making
Champ in-the-making
Now I understand your issue… The form-properties are rendered outside of the activiti-context, so it makes sense the Context throws and EmptyStackEx……
The class org.activiti.explorer.ui.form.FormPropertiesForm only receives the form-properties and no process-context. Your use case makes sense, though. If you want, you could add a processInstanceId and executionId (which may be null) to the render() method of form-properties and make sure it's passed from initiTaskForm() in TaskDetailPanel, al the way down to the actual render call. If you create a pull-request for this, I'm happy to accept it…
Thank you very much 8-) I have created the wish in jira http://jira.codehaus.org/browse/ACT-1500

frederikherema1
Star Contributor
Star Contributor
Thanks… 1500'th issue, hooray!