-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OGM-1103 Prevent ConcurrentModificationException in EventContextManager
When using an OperationCollector and an OperationsQueue in the EventContextManager, you might have ended up with a ConcurrentModificationException as the stateHolder map was modified while iterating over it. We now initialize all the required elements at the start of the event cyle to prevent that.
- Loading branch information
1 parent
f756781
commit a08a24f
Showing
6 changed files
with
201 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
mongodb/src/test/java/org/hibernate/ogm/datastore/mongodb/test/lifecycle/BarKeeper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* Hibernate OGM, Domain model persistence for NoSQL datastores | ||
* | ||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later | ||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. | ||
*/ | ||
package org.hibernate.ogm.datastore.mongodb.test.lifecycle; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
|
||
import org.bson.types.ObjectId; | ||
|
||
/** | ||
* @author Gunnar Morling | ||
*/ | ||
@Entity | ||
public class BarKeeper { | ||
|
||
private ObjectId id; | ||
private String name; | ||
|
||
BarKeeper() { | ||
} | ||
|
||
BarKeeper(ObjectId id, String name) { | ||
this.id = id; | ||
this.name = name; | ||
} | ||
|
||
@Id | ||
public ObjectId getId() { | ||
return id; | ||
} | ||
|
||
public void setId(ObjectId id) { | ||
this.id = id; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
...ava/org/hibernate/ogm/datastore/mongodb/test/lifecycle/PersistOperationCollectorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Hibernate OGM, Domain model persistence for NoSQL datastores | ||
* | ||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later | ||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. | ||
*/ | ||
package org.hibernate.ogm.datastore.mongodb.test.lifecycle; | ||
|
||
import static org.fest.assertions.Assertions.assertThat; | ||
|
||
import java.util.Map; | ||
|
||
import org.bson.types.ObjectId; | ||
import org.hibernate.Transaction; | ||
import org.hibernate.cfg.AvailableSettings; | ||
import org.hibernate.ogm.OgmSession; | ||
import org.hibernate.ogm.cfg.OgmProperties; | ||
import org.hibernate.ogm.compensation.ErrorHandler; | ||
import org.hibernate.ogm.compensation.ErrorHandlingStrategy; | ||
import org.hibernate.ogm.utils.OgmTestCase; | ||
import org.hibernate.ogm.utils.TestForIssue; | ||
import org.junit.Test; | ||
|
||
/** | ||
* Tests for using object ids with MongoDB. | ||
* | ||
* @author Gunnar Morling | ||
* | ||
*/ | ||
public class PersistOperationCollectorTest extends OgmTestCase { | ||
|
||
@Test | ||
@TestForIssue(jiraKey = "OGM-1103") | ||
public void noConcurrentModificationExceptionWhenUsingOperationCollector() { | ||
OgmSession session = openSession(); | ||
Transaction tx = session.beginTransaction(); | ||
|
||
// given | ||
BarKeeper brian = new BarKeeper( new ObjectId(), "Brian" ); | ||
|
||
// when | ||
session.persist( brian ); | ||
session.flush(); | ||
|
||
brian.setName( "Bruce" ); | ||
tx.commit(); | ||
session.clear(); | ||
tx = session.beginTransaction(); | ||
|
||
BarKeeper brianLoaded = session.load( BarKeeper.class, brian.getId() ); | ||
|
||
// then | ||
assertThat( brianLoaded.getId() ).isEqualTo( brian.getId() ); | ||
assertThat( brianLoaded.getName() ).isEqualTo( "Bruce" ); | ||
|
||
tx.commit(); | ||
session.close(); | ||
} | ||
|
||
@Override | ||
protected Class<?>[] getAnnotatedClasses() { | ||
return new Class<?>[] { BarKeeper.class }; | ||
} | ||
|
||
@Override | ||
protected void configure(Map<String, Object> settings) { | ||
settings.put( AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, false ); | ||
settings.put( OgmProperties.ERROR_HANDLER, MyErrorHandler.class ); | ||
} | ||
|
||
public static class MyErrorHandler implements ErrorHandler { | ||
|
||
@Override | ||
public ErrorHandlingStrategy onFailedGridDialectOperation(FailedGridDialectOperationContext context) { | ||
return ErrorHandlingStrategy.ABORT; | ||
} | ||
|
||
@Override | ||
public void onRollback(RollbackContext context) { | ||
} | ||
} | ||
} |