[New] implemented a test to allow multiple operations

This test makes sure that updating after adding, or any other operation
in the same TX works properly. Found a problem where the
PersistenceContext didn't implement hashCode() and equals() which lead
to each operation being added even though a previous operation was
already registered
This commit is contained in:
Robert von Burg 2013-10-19 21:28:11 +02:00
parent 3c623bd20c
commit 3c006b541a
10 changed files with 360 additions and 7 deletions

View File

@ -52,4 +52,43 @@ public class PersistenceContext<T> {
public void setParserFactory(ParserFactory<T> parserFactory) {
this.parserFactory = parserFactory;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.objectRef == null) ? 0 : this.objectRef.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PersistenceContext<?> other = (PersistenceContext<?>) obj;
if (this.objectRef == null) {
if (other.objectRef != null)
return false;
} else if (!this.objectRef.equals(other.objectRef))
return false;
return true;
}
@SuppressWarnings("nls")
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("PersistenceContext [objectRef=");
builder.append(this.objectRef);
builder.append(", object=");
builder.append(this.object);
builder.append(", parserFactory=");
builder.append(this.parserFactory);
builder.append("]");
return builder.toString();
}
}

View File

@ -73,8 +73,50 @@ public class IdOfSubTypeRef extends ObjectRef {
@Override
public <T> PersistenceContext<T> createPersistenceContext(PersistenceTransaction tx) {
PersistenceContextFactoryDelegator ctxFactoryDelegator = tx.getRealm().getCtxFactoryDelegator();
PersistenceContextFactory<T> persistenceContextFactory = ctxFactoryDelegator
.<T> getCtxFactory(this.type);
PersistenceContextFactory<T> persistenceContextFactory = ctxFactoryDelegator.<T> getCtxFactory(this.type);
return persistenceContextFactory.createCtx(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
result = prime * result + ((this.realmName == null) ? 0 : this.realmName.hashCode());
result = prime * result + ((this.subType == null) ? 0 : this.subType.hashCode());
result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IdOfSubTypeRef other = (IdOfSubTypeRef) obj;
if (this.realmName == null) {
if (other.realmName != null)
return false;
} else if (!this.realmName.equals(other.realmName))
return false;
if (this.id == null) {
if (other.id != null)
return false;
} else if (!this.id.equals(other.id))
return false;
if (this.subType == null) {
if (other.subType != null)
return false;
} else if (!this.subType.equals(other.subType))
return false;
if (this.type == null) {
if (other.type != null)
return false;
} else if (!this.type.equals(other.type))
return false;
return true;
}
}

View File

@ -67,8 +67,44 @@ public class IdOfTypeRef extends ObjectRef {
@Override
public <T> PersistenceContext<T> createPersistenceContext(PersistenceTransaction tx) {
PersistenceContextFactoryDelegator ctxFactoryDelegator = tx.getRealm().getCtxFactoryDelegator();
PersistenceContextFactory<T> persistenceContextFactory = ctxFactoryDelegator
.<T> getCtxFactory(this.type);
PersistenceContextFactory<T> persistenceContextFactory = ctxFactoryDelegator.<T> getCtxFactory(this.type);
return persistenceContextFactory.createCtx(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
result = prime * result + ((this.realmName == null) ? 0 : this.realmName.hashCode());
result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IdOfTypeRef other = (IdOfTypeRef) obj;
if (this.realmName == null) {
if (other.realmName != null)
return false;
} else if (!this.realmName.equals(other.realmName))
return false;
if (this.id == null) {
if (other.id != null)
return false;
} else if (!this.id.equals(other.id))
return false;
if (this.type == null) {
if (other.type != null)
return false;
} else if (!this.type.equals(other.type))
return false;
return true;
}
}

View File

@ -8,8 +8,8 @@ import ch.eitchnet.xmlpers.impl.PathBuilder;
public abstract class ObjectRef extends LockableObject {
private String realmName;
private String name;
protected final String realmName;
protected final String name;
protected ObjectRef(String realmName, String name) {
this.realmName = realmName;
@ -44,4 +44,10 @@ public abstract class ObjectRef extends LockableObject {
public String toString() {
return getName();
}
@Override
public abstract boolean equals(Object obj);
@Override
public abstract int hashCode();
}

View File

@ -56,4 +56,29 @@ public class RootRef extends ObjectRef {
String msg = MessageFormat.format("{0} is not a leaf and can thus not have a Persistence Context", getName()); //$NON-NLS-1$
throw new UnsupportedOperationException(msg);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.realmName == null) ? 0 : this.realmName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RootRef other = (RootRef) obj;
if (this.realmName == null) {
if (other.realmName != null)
return false;
} else if (!this.realmName.equals(other.realmName))
return false;
return true;
}
}

View File

@ -63,4 +63,41 @@ public class SubTypeRef extends ObjectRef {
String msg = MessageFormat.format("{0} is not a leaf and can thus not have a Persistence Context", getName()); //$NON-NLS-1$
throw new UnsupportedOperationException(msg);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.realmName == null) ? 0 : this.realmName.hashCode());
result = prime * result + ((this.subType == null) ? 0 : this.subType.hashCode());
result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SubTypeRef other = (SubTypeRef) obj;
if (this.realmName == null) {
if (other.realmName != null)
return false;
} else if (!this.realmName.equals(other.realmName))
return false;
if (this.subType == null) {
if (other.subType != null)
return false;
} else if (!this.subType.equals(other.subType))
return false;
if (this.type == null) {
if (other.type != null)
return false;
} else if (!this.type.equals(other.type))
return false;
return true;
}
}

View File

@ -56,4 +56,35 @@ public class TypeRef extends ObjectRef {
String msg = MessageFormat.format("{0} is not a leaf and can thus not have a Persistence Context", getName()); //$NON-NLS-1$
throw new UnsupportedOperationException(msg);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.realmName == null) ? 0 : this.realmName.hashCode());
result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TypeRef other = (TypeRef) obj;
if (this.realmName == null) {
if (other.realmName != null)
return false;
} else if (!this.realmName.equals(other.realmName))
return false;
if (this.type == null) {
if (other.type != null)
return false;
} else if (!this.type.equals(other.type))
return false;
return true;
}
}

View File

@ -4,10 +4,11 @@ package javanet.staxutils;
* Characters that represent line breaks and indentation. These are represented
* as String-valued JavaBean properties.
*/
@SuppressWarnings("nls")
public interface Indentation {
/** Two spaces; the default indentation. */
public static final String DEFAULT_INDENT = " ";
public static final String DEFAULT_INDENT = " ";
/**
* Set the characters used for one level of indentation. The default is

View File

@ -32,6 +32,7 @@
package javanet.staxutils;
import javanet.staxutils.helpers.StreamWriterDelegate;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
@ -68,6 +69,7 @@ import javax.xml.stream.XMLStreamWriter;
*
* @author <a href="mailto:jk2006@engineer.com">John Kristian</a>
*/
@SuppressWarnings("nls")
public class IndentingXMLStreamWriter extends StreamWriterDelegate implements Indentation {
public IndentingXMLStreamWriter(XMLStreamWriter out) {

View File

@ -21,12 +21,14 @@
*/
package ch.eitchnet.xmlpers.test;
import static ch.eitchnet.xmlpers.test.impl.TestConstants.TYPE_RES;
import static ch.eitchnet.xmlpers.test.model.ModelBuilder.RES_ID;
import static ch.eitchnet.xmlpers.test.model.ModelBuilder.RES_TYPE;
import static ch.eitchnet.xmlpers.test.model.ModelBuilder.assertResource;
import static ch.eitchnet.xmlpers.test.model.ModelBuilder.assertResourceUpdated;
import static ch.eitchnet.xmlpers.test.model.ModelBuilder.createResource;
import static ch.eitchnet.xmlpers.test.model.ModelBuilder.updateResource;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@ -36,12 +38,15 @@ import java.util.List;
import java.util.Properties;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import ch.eitchnet.xmlpers.api.IoMode;
import ch.eitchnet.xmlpers.api.ObjectDao;
import ch.eitchnet.xmlpers.api.PersistenceConstants;
import ch.eitchnet.xmlpers.api.PersistenceTransaction;
import ch.eitchnet.xmlpers.api.XmlPersistenceException;
import ch.eitchnet.xmlpers.objref.IdOfSubTypeRef;
import ch.eitchnet.xmlpers.objref.ObjectRef;
import ch.eitchnet.xmlpers.objref.SubTypeRef;
@ -55,6 +60,9 @@ import ch.eitchnet.xmlpers.test.model.Resource;
*/
public class ObjectDaoResourceTest extends AbstractPersistenceTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
private static final String BASEPATH = "target/db/ObjectDaoTest/"; //$NON-NLS-1$
@BeforeClass
@ -226,4 +234,130 @@ public class ObjectDaoResourceTest extends AbstractPersistenceTest {
assertNull("Expected that resource was deleted by ID, thus can not be read anymore", resource); //$NON-NLS-1$
}
}
@Test
public void shouldFailModifyNotExisting() {
setup(IoMode.SAX);
this.thrown.expect(XmlPersistenceException.class);
this.thrown.expectMessage(containsString("Persistence unit does not exist for")); //$NON-NLS-1$
// update
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
Resource resource = createResource();
tx.getObjectDao().update(resource);
}
}
@Test
public void shouldFailDeleteNotExisting() {
setup(IoMode.SAX);
this.thrown.expect(XmlPersistenceException.class);
this.thrown.expectMessage(containsString("Persistence unit does not exist for")); //$NON-NLS-1$
// delete
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
Resource resource = createResource();
tx.getObjectDao().remove(resource);
}
}
@Test
public void shouldAllowAllOperationsInSameTx() {
setup(IoMode.SAX);
String subType = ModelBuilder.RES_TYPE;
String name = "shouldPersistById "; //$NON-NLS-1$
// create
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
String id = "shouldAllowAllOperationsInSameTx_create"; //$NON-NLS-1$
Resource resource = createResource(id, name, subType);
tx.getObjectDao().add(resource);
}
// create / modify
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
String id = "shouldAllowAllOperationsInSameTx_create_modify"; //$NON-NLS-1$
Resource resource = createResource(id, name, subType);
tx.getObjectDao().add(resource);
tx.getObjectDao().update(resource);
}
// create / delete
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
String id = "shouldAllowAllOperationsInSameTx_create_delete"; //$NON-NLS-1$
Resource resource = createResource(id, name, subType);
tx.getObjectDao().add(resource);
tx.getObjectDao().remove(resource);
}
// create / modify / delete
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
String id = "shouldAllowAllOperationsInSameTx_create_modify_delete"; //$NON-NLS-1$
Resource resource = createResource(id, name, subType);
tx.getObjectDao().add(resource);
tx.getObjectDao().update(resource);
tx.getObjectDao().remove(resource);
}
String id = "shouldAllowAllOperationsInSameTx_read_modify"; //$NON-NLS-1$
// prepare for read/modify
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
Resource resource = createResource(id, name, subType);
tx.getObjectDao().add(resource);
}
// read / modify
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
ObjectRef objectRef = tx.getObjectRefCache().getIdOfSubTypeRef(TYPE_RES, subType, id);
Object resource = tx.getObjectDao().queryById(objectRef);
assertNotNull(resource);
tx.getObjectDao().update(resource);
}
// read / delete
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
ObjectRef objectRef = tx.getObjectRefCache().getIdOfSubTypeRef(TYPE_RES, subType, id);
Object resource = tx.getObjectDao().queryById(objectRef);
assertNotNull(resource);
tx.getObjectDao().remove(resource);
}
// make sure deleted, then recreate
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
ObjectRef objectRef = tx.getObjectRefCache().getIdOfSubTypeRef(TYPE_RES, subType, id);
Object resource = tx.getObjectDao().queryById(objectRef);
assertNull(resource);
// recreate
resource = createResource(id, name, subType);
tx.getObjectDao().add(resource);
}
// read / modify / delete
try (PersistenceTransaction tx = this.persistenceManager.openTx()) {
ObjectRef objectRef = tx.getObjectRefCache().getIdOfSubTypeRef(TYPE_RES, subType, id);
Object resource = tx.getObjectDao().queryById(objectRef);
assertNotNull(resource);
tx.getObjectDao().update(resource);
tx.getObjectDao().remove(resource);
}
}
}