cancel
Showing results for 
Search instead for 
Did you mean: 

problem with adding custom xml parser - added objects disappearing..

atirosselet
Champ in-the-making
Champ in-the-making
I have created a custom parser to add a listener and a form field to each  UserTask in our processes when imported from xml (so we don't have to add them all at design time).   When I debug, it gets called for each task, and the system.out logs are called, showing that it seems to be operating correctly, but after the import, neither the  TaskListener, nor the FormProperty is in the deployed definition.  I check this by instantiating a process and running through it, but nada.  Any ideas?  It appears to be registered correctly in the process engine config the activiti.cfg.xml since it IS being called

  <property name="postBpmnParseHandlers">
        <list>
            <bean class="xxx.yyy.TopBpmnCustomParseListener" />
        </list>
      </property>

The code for the custom parser is :

public class TopBpmnCustomParseListener implements BpmnParseHandler{

  public static final String CUSTOM_TASK_LISTENER = "xxx.yyy.TopTaskEventListener";
  public static final String COMMENT_ATTRIBUTE_FORM_SUFFIX = "_comment";
  public static final String COMMENT_ATTRIBUTE_FORM_NAME = "comment";
  

    @Override
    public Collection<Class<? extends BaseElement>> getHandledTypes() {
        System.out.println("HEEEEE");
        Collection<Class<? extends BaseElement>>  list = new ArrayList<>();
        list.add(UserTask.class);
        return list;
    }
      @Override
    public void parse(BpmnParse bpmnParse, BaseElement element) {

        System.out.println("custom parsing … ");
        if (element instanceof UserTask) {
           
            if (!((UserTask) element).getTaskListeners().stream().anyMatch((x) -> x.getImplementation().equals(CUSTOM_TASK_LISTENER))) {
                System.out.println("Adding task listener…");
                ActivitiListener listener = new ActivitiListener();
                listener.setEvent("all");
                listener.setImplementation(CUSTOM_TASK_LISTENER);
                listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
                ((UserTask) element).getTaskListeners().add(listener);
            }
            String commentFieldName = element.getId() + COMMENT_ATTRIBUTE_FORM_SUFFIX;
            if (!((UserTask) element).getFormProperties().stream().anyMatch(field -> field.getId().equals(commentFieldName))) {
                System.out.println("adding required _comment string field…");
                FormProperty property = new FormProperty();
                property.setId(commentFieldName);
                property.setName(COMMENT_ATTRIBUTE_FORM_NAME);
                property.setType(ELEMENT_FIELD_STRING);
                ((UserTask) element).getFormProperties().add(property);
            }
        }
    }
}

Did I misunderstand something, or is there something else that needs to be set/added?
Thanks
Ati
3 REPLIES 3

atirosselet
Champ in-the-making
Champ in-the-making
I'm going to partly answer myself… but I still don't understand why the previous approach didn't work
Instead extending  AbstractBpmnParseHandler<UserTask>   and  modifying the TaskDefinition

(TaskDefinition) bpmnParse.getCurrentActivity().getProperty(UserTaskParseHandler.PROPERTY_TASK_DEFINITION)
works fine.  the current code is:

public class TopBpmnCustomParseListener extends AbstractBpmnParseHandler<UserTask> {
   
    public static final String COMMENT_ATTRIBUTE_FORM_SUFFIX = "_comment";
    public static final String COMMENT_ATTRIBUTE_FORM_NAME = "comment";

    @Override
    protected Class< ? extends BaseElement> getHandledType() {
        return UserTask.class;
    }

    @Override
    protected void executeParse(BpmnParse bpmnParse, UserTask element) {
        TaskDefinition taskDefinition = (TaskDefinition) bpmnParse.getCurrentActivity().getProperty(UserTaskParseHandler.PROPERTY_TASK_DEFINITION);
        System.out.println("custom processing of :" + ((UserTask) element).getName());
        System.out.println("with properties :"+bpmnParse.getCurrentActivity().getProperties()); 
        // if there are not already any of our listeners attached to the TaskListener.EVENTNAME_ALL_EVENTS event. then add one.
        if (taskDefinition.getTaskListeners().containsKey(TaskListener.EVENTNAME_ALL_EVENTS)){
            if (!taskDefinition.getTaskListeners().get(TaskListener.EVENTNAME_ALL_EVENTS).stream().anyMatch(y->y instanceof TopTaskEventListener)) {
                System.out.println("Adding task listener…to " + ((UserTask) element).getName());
                TaskListener listener = new TopTaskEventListener();
                taskDefinition.addTaskListener(TaskListener.EVENTNAME_ALL_EVENTS, listener);
            }
        }
        String commentFieldName = element.getId() + COMMENT_ATTRIBUTE_FORM_SUFFIX;
        List<FormPropertyHandler> fphList = ((DefaultTaskFormHandler)(taskDefinition.getTaskFormHandler())).getFormPropertyHandlers();
        // if we don't already have an id_comment form property, then add one
        if (!fphList.stream().anyMatch(field -> field.getId().equals(commentFieldName))) {    
            System.out.println("adding required _comment string field…");
            FormPropertyHandler field = new FormPropertyHandler();
            field.setId(commentFieldName);
            field.setType(new StringFormType());
            field.setRequired(false);
            field.setWritable(true);
            field.setReadable(true);
            field.setName(COMMENT_ATTRIBUTE_FORM_NAME);
            field.setVariableName(COMMENT_ATTRIBUTE_FORM_NAME);
            fphList.add(field);
        }
    }
}
and it works fine.  I guess now that doing the same thing with implementing  BpmnParseHandler would have the same effect, but at least here I don't have to cast element to UserTask Smiley Happy Should I assume that what I was doing previously - altering the passed in element has no effect on the parsing process since this is a POST processing.  Unless perhaps I use a preBpmnParseHandlers to change the objects before the normal parsing happens?   I'm not sure if what I'm saying here makes sense though Smiley Happy

In any case… if anyone needs to add FormProperties or TaskListeners.. it works just fine Smiley Happy thanks
Cheers
Ati
P.S.  yes.. I know I keep answering my own questions… Smiley Happy

jbarrez
Star Contributor
Star Contributor
You've stumbled upon something in Activiti v5 that we've fixed in v6.
What you've now discovered that in v5, you need to know the internal model of the 'PVM' (that's where that TaskDefinition is stored) to get the advanced stuff done.

In v6, we've fixed that (read http://www.jorambarrez.be/blog/2015/09/08/activiti-6-an-evolution-of-the-core-engine/). Your first piece of code, would probably work on v6 (haven't tested it), as during runtime execution we simple get the ActivitiListener instances and execute them without any model in between.

bikithalee
Champ in-the-making
Champ in-the-making