Get List processed by Camunda Batch

Hi,
I am needing to get the list that was processed by Camunda, because each of these processed objects changes status and needs this list to continue with our business logic, following you can see how was implemented:

Person.java

public class Person implements Serializable {

	private static final long serialVersionUID = -8678193262118916517L;

	private String id;
	private String name;
	private String lastName;
	private String address;
	private String status;

	// Getters and Setters
}

PersonBatchJobHandler.java

public class PersonBatchJobHandler extends CustomBatchJobHandler<Person> {

	private static final Logger logger = LoggerFactory.getLogger(PersonBatchJobHandler.class.getSimpleName());

	public static final String TYPE = "person-batch-handler";

	@Autowired
	private RuntimeService runtimeService;

	@Override
	public void execute(List<Person> data, CommandContext commandContext) {
		data.forEach(person -> {
			Map<String, Person> variable = new HashMap<>();
			variable.put("person", person);
                        // change the person status to ACTIVE
			runtimeService.startProcessInstanceByKey("registrationPerson", variable);
		});
	}

	@Override
	public String getType() {
		return TYPE;
	}
}

The next step is to execute the custom batch:

List<Person> persons = new ArrayList<>();
Person person1 = new Person();
person1.setId("1");
person1.setName("Tom");
person1.setLastName("Reid");
person1.setAddress("...");
person1.setStatus("NO_ACTIVE");
persons.add(person1);
		
Person person2 = new Person();
person2.setId("2");
person2.setName("Wendell");
person2.setLastName("Jefferson");
person2.setAddress("...");
person2.setStatus("NO_ACTIVE");
persons.add(person2);

CustomBatchBuilder.of(persons).configuration(engineConfiguration).jobHandler(personBatchJobHandler).create();

// Continue with the business logic with the list of persons processed by CustomBatchBuilder

In the code above the list of persons has the object id Persons@79c4f23b, but when PersonBatchJobHandler has executed, the same list change the object id to Persons@3244790c and each object id of the list change too, then when the program continues with the business logic I suppose that I get the list of persons but with the new status ACTIVE of each element of the list, it looks like the execute method from PersonBatchJobHandler create a new list to be executed on batch, so my question is: is it possible to get the list of persons which was processed on batch ? or exist the way to keep the same list which was consumed by PersonBatchJobHandler ?

Thanks in advance,

Juan.

Hi Juan,

this is because the Person 1 you put into the Batch, an the Person 1 which will get passed to the Batch Handler is not the Same. When Creating a Batch, the data will be serialized and saved to database. This is because Camunda Batch works with async jobs. (So a big advantage is that even if the engine does a restart, the batch will continue)

So the job handler will just get a new deserialized List with the Person objects. And when you change something in the object, it will not be saved. Batch is not designed to work like this.

In the most cases where it is used, the batch data just holds a list of reference IDs. So in the batch handler, it just gets the IDs which should get processed.

Best Regards,
Patrick

Hi Patrick,

Thanks for your answer!

“So the job handler will just get a new deserialized List with the Person objects. And when you change something in the object, it will not be saved. Batch is not designed to work like this.”
the handler when do change in each object, that occurs when the runtimeService execute the task, Do you have any suggestion to continue working with the list which was processed ?

“So in the batch handler, it just gets the IDs which should get processed.”
This part is not clear for me, What do you mean by the IDs, what could I do with them?

Thanks a lot!

Juan.

Maybe I can explain it better with a real live example which I’ve implemented at one of my customers:

We used batch for doing reassignment (because of some business rule changes, it could be that other users should work on the task). So when we create the batch, we just collect the list of taskIds which should get processed by the batch handler. The batch handler then uses just the ID to get related data from some business service and does (if needed) the reassignment of the single task for the given id).

So in your case, you could think about just passing the person ids to batch. Additionally you have some PersonRepo which holds the person objects. So in your handler you can get the person from there, and also update it later after processing. Batch is just used to split the workload in multiple (parallel) chunks, and to make sure that it still gets processed even if the backend gets restarted.

Is it now a little bit clearer what I mean?

Cheers,
Patrick

1 Like

Hi Patrick,

Yes it’s a little bit clear now… so let me show you what corrections I did:
PersonBatchJobHandler.java

public class PersonBatchJobHandler extends CustomBatchJobHandler<Person> {

	private static final Logger logger = LoggerFactory.getLogger(PersonBatchJobHandler.class.getSimpleName());

	public static final String TYPE = "person-batch-handler";

	@Autowired
	private RuntimeService runtimeService;
        
    List<Person> dataProcessed = new ArrayList<>();

	@Override
	public void execute(List<Person> data, CommandContext commandContext) {
		data.forEach(person -> {
			Map<String, Person> variable = new HashMap<>();
			variable.put("person", person);
                        // change the person status to ACTIVE
			runtimeService.startProcessInstanceByKey("registrationPerson", variable);
		});
        // the new list of persons with the new status
        dataProcessed = data;
	}

	@Override
	public String getType() {
		return TYPE;
	}
       
	public List<Person> getDataProcessed() {
		return dataProcessed;
	}
}

and then I did the following:

List<Person> persons = new ArrayList<>();
Person person1 = new Person();
person1.setId("1");
person1.setName("Tom");
person1.setLastName("Reid");
person1.setAddress("...");
person1.setStatus("NO_ACTIVE");
persons.add(person1);
		
Person person2 = new Person();
person2.setId("2");
person2.setName("Wendell");
person2.setLastName("Jefferson");
person2.setAddress("...");
person2.setStatus("NO_ACTIVE");
persons.add(person2);

CustomBatchBuilder.of(persons).configuration(engineConfiguration).jobHandler(personBatchJobHandler).create();

persons = personBatchJobHandler.getDataProcessed();

// Continue with the business logic with the list of persons processed by CustomBatchBuilder

As you can see in this line:
persons = personBatchJobHandler.getDataProcessed()
I could get the list that was processed but in the line:
CustomBatchBuilder.of(persons).configuration(engineConfiguration).jobHandler(personBatchJobHandler).create();
This execution is asynchronous so the line which I could get the new list of persons processed, can not get it because this executes first than the “CustomBatchBuilder…” so now my question is… is it possible to know when the batch is finished? exist some routine in this batch extension to ask or testing when the batch is finished?

Thanks very much!

Juan.