cancel
Showing results for 
Search instead for 
Did you mean: 

Activiti Error Handling

fritz128
Champ in-the-making
Champ in-the-making
What I have:
Non-Activiti processes (saving to DB) in Activiti Service Task. I want to rollback Activiti context on error

What a problem:
Activiti context doesn't rollback.

My code:]
In this service task I create new client entity and persist it. Client entity has Unique constraint, so the try{} section may fail. When it happens, I see in TaskTwo that execution.getVariable("client") != null


@Service
public class AddClientService implements ActivityBehavior {

    @Override
    public void execute(ActivityExecution execution) throws Exception {
        PvmTransition transition = null;

        Client client = new Client();
        client.setFirstName("John");
        client.setLastName("Smith"); // Have unique constraint

        execution.setVariable("client", client); // need to be rollbacked in case of error

        Engine engine = Engine.getInstance();
        SessionFactory sessionFactory = engine.getHibernateSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        try {
            session.save(client);
            session.getTransaction().commit();
            transition = execution.getActivity().findOutgoingTransition("toTaskOneFlow");
        } catch (Exception ex) {
            transition = execution.getActivity().findOutgoingTransition("toTaskTwoFlow");
        } finally {
            session.close();
        }
        execution.take(transition);
    }
}


Questions:
1. Why execution.getVariable("client") != null in the next task after error happens?
2. Do I need manually remove all variables from Activiti context after error?
3. May be it is better to use compensation end event in my case?
10 REPLIES 10

pkonyves
Champ in-the-making
Champ in-the-making
I would catch it if I could but we build a gui for Activiti with JSF. Processes have their own facelets for forms with complete buttons like h:commandButton action="BusinessProcess#completeTask(taskId)". I don't think it's the most practical way, but we didn't want to force workflows to use our own API, they can use standard Activiti API the same way Activiti in action describes the JSF integration. I am telling it because this excludes the idea of just wrapping the completeTask() method in a try-catch block.

I can catch the exception in the JSF ErrorHandler and show it to the user: OK. But also want to have it logged within the process to save this information as a process variable for later time. I don't want to do in the JSF ErrorHandler, because I would kill myself for making calls to the business tier from the "last rock" of my application, the ErrorHandler, totally out the JSF lifecycle etc.

I could probably automate this behavior with a custom CommandInterceptor… Anyways, if you don't have a better idea, I think a new transaction is fine.

ps.: You still mentioned synchronously, but I also want it to work on async tasks

Thanks