From bf41ed71183e97f14ee338a9b835f7a9f2f96d26 Mon Sep 17 00:00:00 2001 From: lipido Date: Wed, 27 Dec 2017 21:43:57 +0100 Subject: [PATCH] Fixes ConcurrentModificationException in removeEmployee A ConcurrentModificationException is raised when removing an item from projectAssignments during its iteration. In order to avoid this, a copy of the collection is made to iterate over it. --- .../dgpena/siexample/persistence/Project.java | 5 ++++- .../siexample/persistence/ProjectsTest.java | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/dgpena/siexample/persistence/Project.java b/src/main/java/dgpena/siexample/persistence/Project.java index b57a0d9..902f492 100644 --- a/src/main/java/dgpena/siexample/persistence/Project.java +++ b/src/main/java/dgpena/siexample/persistence/Project.java @@ -72,7 +72,9 @@ public class Project { } public void removeEmployee(Employee e) { - for (ProjectAssignment pa: this.projectAssignments) { + // create a copy of the this.projectAssignments in order to avoid ConcurrentModificationException + Set projectAssignmentsCopy = new HashSet(this.projectAssignments); + for (ProjectAssignment pa: projectAssignmentsCopy) { if (pa.getEmployee().equals(e)) { // this will call internalRemoveProjectAssignment pa.setProject(null); @@ -83,6 +85,7 @@ public class Project { } void internalRemoveProjectAssignment(ProjectAssignment projectAssignment) { + System.err.println("====>internal remove project assingment"); this.projectAssignments.remove(projectAssignment); } diff --git a/src/test/java/dgpena/siexample/persistence/ProjectsTest.java b/src/test/java/dgpena/siexample/persistence/ProjectsTest.java index b40b029..f251850 100644 --- a/src/test/java/dgpena/siexample/persistence/ProjectsTest.java +++ b/src/test/java/dgpena/siexample/persistence/ProjectsTest.java @@ -77,9 +77,16 @@ public class ProjectsTest extends SQLBasedTest { // insert an employee previously with JDBC int employeeId = insertAnEmployee(); - // assign the employee to the project (which should be removed due to CascadeType.REMOVE - // in Project.projectAssignments) + // insert a second employee previously with JDBC (this is the employee that will be removed from the project) + int employeeId2 = insertAnEmployee(); + + + // assign those employees to the project Statement statement = jdbcConnection.createStatement(); + statement.executeUpdate("INSERT INTO ProjectAssignment(project_id, employee_id) values("+projectId+", " + +employeeId2+")", Statement + .RETURN_GENERATED_KEYS); + statement = jdbcConnection.createStatement(); statement.executeUpdate("INSERT INTO ProjectAssignment(project_id, employee_id) values("+projectId+", " +employeeId+")", Statement .RETURN_GENERATED_KEYS); @@ -88,16 +95,16 @@ public class ProjectsTest extends SQLBasedTest { em.getTransaction().begin(); Project p = new Projects(em).findById(projectId); - Employee e = new Employees(em).findById(employeeId); + Employee e = new Employees(em).findById(employeeId2); p.removeEmployee(e); em.getTransaction().commit(); - // ensure that the project assignment does not exist + // ensure that the project assignment for employee 2 does not exist statement = jdbcConnection.createStatement(); ResultSet res = statement.executeQuery("SELECT COUNT(*) as total from ProjectAssignment where employee_id = " + - ""+employeeId+" and project_id = "+projectId); + ""+employeeId2+" and project_id = "+projectId); res.next(); assertEquals(0, res.getInt("total")); } -- 2.18.1