-3

I am working on a Spring MVC project and I am getting an ArrayOutOfBound exception. If this was Java 7 then I would have no problem, but since it's Java 8 and I am new to it, I have no idea what the problem is. I have searched for about two days but have no luck. I would appreciate the help.

Now the out of bounds is caused by ProjectService class and specifically the public Project find(Long projectId)....

Now my service class is:

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import com.spring.project.model.Project;

@Service
public class ProjectService {

    private List<Project> projects = new LinkedList<>();

    public ProjectService(){
        Project javaProject = this.createProject("Java Project", "This is a Java Project");
        Project javascriptProject = this.createProject("Javascript Project", "This is a Javascript Project");
        Project htmlProject = this.createProject("HTML Project", "This is an HTML project");

        this.projects.addAll(Arrays.asList(new Project[]{javaProject,javascriptProject, htmlProject}));
    }

    public List<Project> findAll(){
        return this.projects;
    }

    public Project find(Long projectId){
        return this.projects.stream().filter(p -> {
            return p.getProjectId().equals(projectId);
        }).collect(Collectors.toList()).get(0);
    }

    private Project createProject(String title, String description){
        Project project = new Project();

        project.setName(title);
        project.setAuthorizedFunds(new BigDecimal("100000"));
        project.setAuthorizedHours(new BigDecimal("1000"));
        project.setDescription(description);
        project.setSponsor("NASA");
        project.setYear("2016");
        project.setSpecial(true);
        project.setType("single");

        return project;

    }

}

Now my controller looks like this:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.spring.project.services.ProjectService;

@Controller
@RequestMapping("/project")
public class ProjectController {


    @Autowired
    private ProjectService projectService;

    @RequestMapping(value="/{projectId}")
    public String findProject(Model model, @PathVariable("projectId") Long projectId){
        model.addAttribute("project", this.projectService.find(projectId));
        return "project";
    }

    @RequestMapping(value="/find")
    public String find(Model model){
        model.addAttribute("projects", this.projectService.findAll());
        return "projects";
    }
}
Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Leonel
  • 1
  • 2
  • You like redundant code, do you? Instead of `Arrays.asList(new Project[]{x,y,z})`, you can just write `Arrays.asList(x,y,z)` and`.filter(p -> { return p.getProjectId().equals(projectId); })`, can be replaced with `.filter(p -> p.getProjectId().equals(projectId))`. And if you are only interested in the first match, use `findFirst()` instead of collecting everything in a `List`. – Holger Jul 01 '16 at 11:46

2 Answers2

1

Withouth a stack trace it's hard to tell, but this code fragment looks suspicious:

return this.projects.stream().filter(p -> {
    return p.getProjectId().equals(projectId);
}).collect(Collectors.toList()).get(0);

If method invocation collect(Collectors.toList()) returns an empty list, then getting the first element of the empty list will result in java.lang.IndexOutOfBoundsException. Consider using Streams#findFirst that returns Optional instead of collect(Collectors.toList()).get(0) that can throw exception.

Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Tomasz Bekas
  • 666
  • 6
  • 15
  • Of course, if the OP then unconditionally calls `get()` on the `Optional`, it won’t help. The key point is dealing with the possibility of not finding a match. But at least, `findFirst()` is more efficient. – Holger Jul 01 '16 at 11:48
  • That's true. I assumed that OP will read documentation and handle this case. – Tomasz Bekas Jul 01 '16 at 22:41
0

The problem is with the lambda expression in filter. Remove the return statement from the filter and try:

i.e. your code is very verbose and it should read as below:

return this.projects.stream().filter(p -> p.getProjectId().equals(projectId)).findFirst().get();

When you try to search an id that is not present you will get java.util.NoSuchElementException which is more meaningful. get(0) is the root cause of your java.lang.IndexOutOfBoundsException.

Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Naresh Kumar
  • 673
  • 7
  • 17
  • As @Holger explained, invocation of `get()` on empty Optional will result in NoSuchElementException. You should either use `orElse`/`orElseGet` method or check the presence with the `isPresent()` and if present then you can safely call `get()`. – Tomasz Bekas Jul 01 '16 at 22:46