I am using SAP BPM API's to fetch currently running process instance and the task belonging to the running process instance. I have return below method on an EJB Class which does the job, however it is extremely slow and have n2 complexity which is making it dangerous to move on production system as the process instances would definitely increase over the time and so does the number of tasks for each process instance I need help to optimize the method and suggestions to make it faster - public List<WorkItemDto> getMyWorkItem() {    List<WorkItemDto> workItemList = new ArrayList<WorkItemDto>();    WorkItemDto wbDto;    // Task statuses we are interested in    Set<Status> statuses = new HashSet<Status>();    statuses.add(Status.READY);    statuses.add(Status.CREATED);    statuses.add(Status.IN_PROGRESS);    statuses.add(Status.RESERVED);    List<TaskAbstract> taskAbstracts = BPMFactory.getTaskInstanceManager()            .getMyTaskAbstracts(statuses, null,                    new TaskAbstractCustomAttributesCriteria());//      System.out.println(>>TaskAbstract count without Substituted user: +taskAbstracts.size());    if (taskAbstracts.isEmpty()){        taskAbstracts = new ArrayList<TaskAbstract>(BPMFactory.getTaskInstanceManager().getTaskAbstractsForAllMySubstitutedUsers(statuses));    } else{        taskAbstracts.addAll(BPMFactory                .getTaskInstanceManager().getTaskAbstractsForAllMySubstitutedUsers(statuses));    }//      System.out.println(>>TaskAbstract count with Substituted user: +taskAbstracts.size());    for (TaskAbstract taskAbstract : taskAbstracts) {        ProcessInstance processInstance = BPMFactory                .getProcessInstanceManager()                .getProcessInstanceForTaskInstanceId(taskAbstract.getId());         wbDto = new WorkItemDto();         ProcessDefinition processDefinition = BPMFactory         .getProcessDefinitionManager         ().getProcessDefinition(processInstance.getDefinitionId());         wbDto.setProcessDefinitionId(processInstance.getDefinitionId().toString());          wbDto.setProcessEndDate(processInstance.getEndDate());         wbDto.setProcessInstanceId(processInstance.getId().toString());          wbDto.setProcessModelId(processInstance.getModelId().toString());         wbDto.setProcessInitiator(processInstance.getProcessInitiator().getUniqueID().toString());         wbDto.setRootProcessInstanceId(processInstance.getRootProcessInstanceId()!=null?processInstance.getRootProcessInstanceId().toString():null);         wbDto.setParentProcessInstanceId(processInstance.getParentProcessInstanceId()!=null?processInstance.getParentProcessInstanceId().toString():null);         wbDto.setProcessStartDate(processInstance.getStartDate());          wbDto.setProcessStatus(processInstance.getStatus().toString());         wbDto.setProcessSubject(processInstance.getSubject());         wbDto.setProcessIsConditionalStart(processDefinition.isConditionalStart());         wbDto.setEscalated(taskAbstract.isEscalated());        URL executionUrl = BPMFactory.getTaskInstanceManager()                .generateTaskExecutionUrl(taskAbstract.getId());        try {            wbDto.setExecutionUrl(executionUrl.toURI().toString());        } catch (URISyntaxException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        wbDto.setActivationTime(taskAbstract.getActivationTime());        wbDto.setProcessName(processInstance.getName());        wbDto.setCompleteByTime(taskAbstract.getCompleteByTime());        wbDto.setCreatedTime(taskAbstract.getCreatedTime());        wbDto.setCustomAttribute(taskAbstract.getCustomAttributeValues());        wbDto.setDefinitionId(taskAbstract.getDefinitionId().toString());        wbDto.setDescription(taskAbstract.getDescription());        wbDto.setExpirationTime(taskAbstract.getExpirationTime());        wbDto.setId(taskAbstract.getId().toString());        wbDto.setModelId(taskAbstract.getModelId().toString());        wbDto.setName(taskAbstract.getName());        wbDto.setPriority(taskAbstract.getPriority().toString());        wbDto.setStartByTime(taskAbstract.getStartByTime());        wbDto.setStatus(taskAbstract.getStatus().toString());        wbDto.setSubject(taskAbstract.getSubject());        wbDto                .setTaskInitiator(taskAbstract.getTaskInitiator() != null ? taskAbstract                        .getTaskInitiator().getDisplayName().toString() != null ? taskAbstract                        .getTaskInitiator().getDisplayName().toString()                        : NA                        : NA);        wbDto.setTaskType(taskAbstract.getTaskType());        List<WorkItemNotesDto> workItemNoteList = new ArrayList<WorkItemNotesDto>();        WorkItemNotesDto wNote;        for (Note note : BPMFactory.getTaskInstanceManager().getNotes(                taskAbstract.getId())) {            wNote = new WorkItemNotesDto();            wNote.setContent(note.getContent());            wNote.setCreatedBy(note.getCreatedBy().getFirstName());            wNote.setCreatedOn(note.getCreatedOn());            wNote.setId(note.getId().toString());            workItemNoteList.add(wNote);        }        wbDto.setWorkItemNotesList(workItemNoteList);        workItemList.add(wbDto);    }     Collections.sort(workItemList, new Comparator<WorkItemDto>(){           public int compare (WorkItemDto m1, WorkItemDto m2){               return m2.getCreatedTime().compareTo(m1.getCreatedTime());           }       });     System.err.println(>>Out from My WorkItem at: +new Date().getTime());    return workItemList;}
SAP BPM API - Fetching ProcessInstance & TaskAbstract
java