Search code examples
javalistrestfor-loophttp-status-code-500

Removing second item from a list crashes REST API


I'm trying to add a feature to my REST API where it filters data by year so only the objects will show that has the same year I am requesting.

The path that I am using to test this feature is

  http://localhost:8080/Assignment2C/beers?year=2019

it goes to a 500 error

in the Beers_Service.java where it iterates through the list the second time is where it fails

public List<Beers> getAllBeersByYear(int year) {
EntityManager em = DBUtil.getEMF().createEntityManager();

List<Beers> list = null;

try {
    list = em.createNamedQuery("Beers.findAll", Beers.class)
            .getResultList();
    if (list == null || list.isEmpty()) {
        list = null;
    }

} finally {
    em.close();
}
Calendar cal = Calendar.getInstance();
for(Beers beer: list){
    cal.setTime(beer.getLastMod());
    if(cal.get(Calendar.YEAR)!=year){

        list.remove(beer);
    }
}
return list;

All of the dates in the Database is 2019 except for the first object which is 2018

when using the debugger, it iterates through the for loop and because the first entry in the database is 2018, it removes it fine, after removing the object, it goes back to the top of the for loop an at this line crashes.

 for(Beers beer: list){

When in the debug mode after it breaks the for loop, it goes into this source code in the

                   beforeExecute(wt, task);
                    try {
                        task.run();
                        afterExecute(task, null);
                    } catch (Throwable ex) {
                        afterExecute(task, ex);
                        throw ex;
                    }

at the line

afterExecute(task, null);

the stack trace I get is

<h1>HTTP Status 500 – Internal Server Error</h1>
    <hr class="line" />
    <p><b>Type</b> Exception Report</p>
    <p><b>Message</b> Request processing failed; nested exception is java.util.ConcurrentModificationException</p>
    <p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.
    </p>
    <p><b>Exception</b></p>
    <pre>org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.util.ConcurrentModificationException
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
</pre>
    <p><b>Root Cause</b></p>
    <pre>java.util.ConcurrentModificationException
    java.base&#47;java.util.Vector$Itr.checkForComodification(Vector.java:1320)
    java.base&#47;java.util.Vector$Itr.next(Vector.java:1276)
    main.Beers_Service.getAllBeersByYear(Beers_Service.java:53)
    main.Beers_Controller.GetAllBreweries(Beers_Controller.java:72)
    java.base&#47;jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    java.base&#47;jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    java.base&#47;jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.base&#47;java.lang.reflect.Method.invoke(Method.java:567)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

Solution

  • You shouldn't modify the collection while iterating over it: https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html

    " For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception."