1

I am using Java StreamSupport to stream on Iterable return from repository method inside of @Transactional method in service layer.

Svc:

@Transactional(readOnly = true)
public Map<String, Map<String, Object>> getAllProjects() {
    return StreamSupport.stream(projectRepo.findAllByOrderByNameAsc().spliterator(), true)
        .collect(
            LinkedHashMap::new,
            (map, projectItem) -> map.put(projectItem.getName(), populateProjectItem(projectItem)),
            (map, projectMap) -> map.putAll(projectMap)
        );
}

 private Map<String, Object> populateProjectItem(final Project project) {
     return ImmutableMap.of(
        "id", project.getId(),
        "name", project.getName(),
        "taskList", project.getTaskList().stream()
              .map(taskItem -> ImmutableMap.of(
                 "id", taskItem.getId()
              )
             .collect(Collectors.toList())
     );
 }   

I am not sure what I am doing wrong but it gives me nullpointer on Task Id in test case. project.getTaskList() is lazy fetch loaded.

Am i missing something ?

  • 1
    what in the world are you trying to do here? what does `findAllByOrderByNameAsc` returns? And why do you think that parallel is a good option here? – Eugene Feb 28 '18 at 19:21
  • @Eugene `findAllByOrderByNameAsc` returns `Iterable` (Repository method in spring). I am doing the parallel stream for the purpose of storing the sequence returned by above method. with `LinkedHashMap::new`. –  Feb 28 '18 at 21:42
  • You did not explain why you are using a *parallel* stream here. From all that you have shown, we can conclude that it’s likely much slower than using a sequential stream for this operation. Besides that, lazily populated JPA lists and streams are known to break, unless you use an up-to-date version, see [here](https://stackoverflow.com/a/37926832/2711488) and related [here](https://stackoverflow.com/a/28859568/2711488). But it’s not clear whether that’s your actual issue as elements should not spuriously be `null`, so there might be another problem. – Holger Mar 01 '18 at 11:05
  • @Holger Thank you for the valuable inputs and reference material. I fixed the issue by changing it to sequential stream and lazy loading the list. i.e. `(map, projectItem) -> { //loading lazy relationship projectItem.getTaskList().size(); map.put(projectItem.getName(), populateProjectItem(projectItem))} ` –  Mar 05 '18 at 19:46
  • @Holger `getTaskList` is model getter for `taskList` arraylist in `project` entity. Do you recommend this approach of lazy load or calling separate repo method to return tasks by project Id and then using set task list method? –  Mar 05 '18 at 19:48
  • There is not much laziness; you still process the entire list right at this point. But I don’t know whether it matters for your project. The only thing I can say, is, keep it simple… – Holger Mar 06 '18 at 07:20
  • @Holger Sounds good, Thank you for guiding I really appreciate your time and help. –  Mar 06 '18 at 18:36

0 Answers0