Source:
public Collection<CaseMilestoneInstance> getCaseInstanceMilestones(String caseId, boolean achievedOnly, QueryContext queryContext) { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceByCorrelationKey(correlationKeyFactory.newCorrelationKey(caseId)); if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) { throw new CaseNotFoundException("No case instance found with id " + caseId + " or it's not active anymore"); } CorrelationKey correlationKey = correlationKeyFactory.newCorrelationKey(caseId); Collection<org.jbpm.services.api.model.NodeInstanceDesc> nodes = runtimeDataService.getNodeInstancesByCorrelationKeyNodeType(correlationKey, Arrays.asList(ProcessInstance.STATE_ACTIVE, ProcessInstance.STATE_ABORTED), Arrays.asList("MilestoneNode"), queryContext); Map<String, List<CaseMilestoneInstance>> milestonesGroup = nodes.stream() .map(n -> (NodeInstanceDesc) n) .filter(n -> n.getType() == 1) .map(n -> new CaseMilestoneInstanceImpl(String.valueOf(n.getId()), n.getName(), true, n.getDataTimeStamp())) .collect(Collectors.groupingBy(CaseMilestoneInstance::getName)); List<CaseMilestoneInstance> milestones = milestonesGroup.values().stream().map(e -> e.stream().min((o1, o2) -> o1.getAchievedAt().compareTo(o2.getAchievedAt())).get()).collect(toList()); List<String> foundMilestones = milestones.stream().map(e -> e.getName()).collect(toList()); if (!achievedOnly) { CaseDefinition caseDef = getCase(pi.getDeploymentId(), pi.getProcessId()); caseDef.getCaseMilestones().stream() .filter(cm -> !foundMilestones.contains(cm.getName())) .map(cm -> new CaseMilestoneInstanceImpl(cm.getId(), cm.getName(), false, null)) .forEach(cmi -> milestones.add(cmi)); } return applyPagination(milestones, queryContext); }

Target:
public Collection<CaseMilestoneInstance> getCaseInstanceMilestones(String caseId, boolean achievedOnly, QueryContext queryContext) { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceByCorrelationKey(correlationKeyFactory.newCorrelationKey(caseId)); if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) { throw new CaseNotFoundException("No case instance found with id " + caseId + " or it's not active anymore"); } CorrelationKey correlationKey = correlationKeyFactory.newCorrelationKey(caseId); Collection<org.jbpm.services.api.model.NodeInstanceDesc> nodes = runtimeDataService.getNodeInstancesByCorrelationKeyNodeType(correlationKey, Arrays.asList(ProcessInstance.STATE_ACTIVE, ProcessInstance.STATE_ABORTED), Arrays.asList("MilestoneNode"), queryContext); Map<String, List<CaseMilestoneInstance>> milestonesGroup = nodes.stream() .map(n -> (NodeInstanceDesc) n) .filter(n -> n.getType() == 1) .map(n -> new CaseMilestoneInstanceImpl(String.valueOf(n.getId()), n.getName(), true, n.getDataTimeStamp())) .collect(Collectors.groupingBy(CaseMilestoneInstance::getName)); List<CaseMilestoneInstance> milestones = milestonesGroup.values().stream().map(e -> e.stream().min(this::compareMilestones).get()).collect(toList()); List<String> foundMilestones = milestones.stream().map(CaseMilestoneInstance::getName).collect(toList()); if (!achievedOnly) { CaseDefinition caseDef = getCase(pi.getDeploymentId(), pi.getProcessId()); caseDef.getCaseMilestones().stream() .filter(cm -> !foundMilestones.contains(cm.getName())) .map(cm -> new CaseMilestoneInstanceImpl(cm.getId(), cm.getName(), false, null)) .forEach(cmi -> milestones.add(cmi)); } List<CaseMilestoneInstance> sortedMilestones = milestones.stream().sorted(this::compareMilestones).collect(toList()); return applyPagination(sortedMilestones, queryContext); }