blob: e4645c73a700acfbf66c15cd10a56795b06ee270 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.callbacks;
import java.util.Set;
import java.util.HashSet;
import javax.persistence.EntityManager;
import javax.persistence.RollbackException;
import org.apache.openjpa.persistence.OpenJPAPersistence;
import org.apache.openjpa.persistence.callbacks.ExceptionsFromCallbacksEntity.CallbackTestException;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
import org.apache.openjpa.enhance.PersistenceCapable;
/**
* Tests against JPA section 3.5's description of callback exception handling.
*/
public class TestExceptionsFromCallbacks
extends SingleEMFTestCase {
public static boolean testRunning = false;
@Override
public void setUp() {
Set needEnhancement = new HashSet();
needEnhancement.add(
"testPostUpdateExceptionDuringFlushWithNewInstance");
needEnhancement.add(
"testPreUpdateExceptionDuringFlushWithExistingFlushedInstance");
needEnhancement.add(
"testPreUpdateExceptionDuringCommitWithExistingFlushedInstance");
needEnhancement.add(
"testPostUpdateExceptionDuringFlushWithExistingFlushedInstance");
needEnhancement.add(
"testPostUpdateExceptionDuringCommitWithExistingFlushedInstance");
if (!PersistenceCapable.class.isAssignableFrom(
ExceptionsFromCallbacksEntity.class)
&& needEnhancement.contains(getName()))
// actually, we really only need redef
fail("this test method does not work without enhancement");
setUp(ExceptionsFromCallbacksEntity.class, CLEAR_TABLES);
testRunning = true;
}
@Override
public void tearDown() throws Exception {
testRunning = false;
super.tearDown();
}
public void testPrePersistException() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setThrowOnPrePersist(true);
try {
em.persist(o);
fail("persist should have failed");
} catch (CallbackTestException cte) {
// transaction should be still active, but marked for rollback
assertTrue(em.getTransaction().isActive());
assertTrue(em.getTransaction().getRollbackOnly());
} finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
}
public void testPrePersistExceptionOnMerge() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setThrowOnPrePersist(true);
try {
em.merge(o);
fail("merge should have failed");
} catch (CallbackTestException cte) {
// transaction should be still active, but marked for rollback
assertTrue(em.getTransaction().isActive());
assertTrue(em.getTransaction().getRollbackOnly());
} finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
}
public void testPostPersistExceptionDuringFlush() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setThrowOnPostPersist(true);
em.persist(o);
mutateAndFlush(em, o);
}
private void mutateAndFlush(EntityManager em,
ExceptionsFromCallbacksEntity o) {
o.setStringField("foo");
flush(em);
}
private void flush(EntityManager em) {
try {
em.flush();
fail("flush should have failed");
} catch (CallbackTestException cte) {
// transaction should be still active, but marked for rollback
assertTrue(em.getTransaction().isActive());
assertTrue(em.getTransaction().getRollbackOnly());
} finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
}
public void testPostPersistExceptionDuringCommit() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setThrowOnPostPersist(true);
em.persist(o);
mutateAndCommit(em, o);
}
private void mutateAndCommit(EntityManager em,
ExceptionsFromCallbacksEntity o) {
o.setStringField("foo");
commit(em);
}
private void commit(EntityManager em) {
try {
em.getTransaction().commit();
fail("commit should have failed");
} catch (RollbackException re) {
assertEquals(CallbackTestException.class,
re.getCause().getClass());
// transaction should be rolled back at this point
assertFalse(em.getTransaction().isActive());
} finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
}
public void testPrePersistExceptionDuringFlushWithNewFlushedInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPrePersist(true);
// should pass; pre-persist should not be triggered
o.setStringField("foo");
em.flush();
em.getTransaction().commit();
em.close();
}
public void testPrePersistExceptionDuringCommitWithNewFlushedInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPrePersist(true);
// should pass; pre-persist should not be triggered
o.setStringField("foo");
em.getTransaction().commit();
em.close();
}
public void testPostPersistExceptionDuringFlushWithNewFlushedInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPostPersist(true);
// should pass; post-persist should not be triggered
o.setStringField("foo");
em.flush();
em.getTransaction().commit();
em.close();
}
public void testPostPersistExceptionDuringCommitWithNewFlushedInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPostPersist(true);
// should pass; post-persist should not be triggered
o.setStringField("foo");
em.getTransaction().commit();
em.close();
}
public void testPreUpdateExceptionWithNewInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setThrowOnPreUpdate(true);
em.persist(o);
o.setStringField("foo");
em.getTransaction().commit();
em.close();
}
public void testPostUpdateExceptionDuringFlushWithNewInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setThrowOnPostUpdate(true);
em.persist(o);
o.setStringField("foo");
em.flush();
em.getTransaction().commit();
em.close();
}
public void testPostUpdateExceptionDuringCommitWithNewInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setThrowOnPostUpdate(true);
em.persist(o);
o.setStringField("foo");
em.getTransaction().commit();
em.close();
}
public void testPreUpdateExceptionDuringFlushWithNewFlushedInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPreUpdate(true);
mutateAndFlush(em, o);
}
public void testPreUpdateExceptionDuringCommitWithNewFlushedInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPreUpdate(true);
mutateAndCommit(em, o);
}
public void testPostUpdateExceptionDuringFlushWithNewFlushedInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPostUpdate(true);
mutateAndFlush(em, o);
}
public void testPostUpdateExceptionDuringCommitWithNewFlushedInstance() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPostUpdate(true);
mutateAndCommit(em, o);
}
public void testPreUpdateExceptionDuringFlushWithExistingInstance() {
Object oid = insert("new instance");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o =
em.find(ExceptionsFromCallbacksEntity.class, oid);
o.setThrowOnPreUpdate(true);
mutateAndFlush(em, o);
}
private Object insert(String s) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setStringField(s);
em.persist(o);
em.getTransaction().commit();
em.close();
return o.getId();
}
public void testPreUpdateExceptionDuringCommitWithExistingInstance() {
Object oid = insert("new instance");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o =
em.find(ExceptionsFromCallbacksEntity.class, oid);
o.setThrowOnPreUpdate(true);
mutateAndCommit(em, o);
}
public void testPostUpdateExceptionDuringFlushWithExistingInstance() {
Object oid = insert("new instance");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o =
em.find(ExceptionsFromCallbacksEntity.class, oid);
o.setThrowOnPostUpdate(true);
mutateAndFlush(em, o);
}
public void testPostUpdateExceptionDuringCommitWithExistingInstance() {
Object oid = insert("new instance");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o =
em.find(ExceptionsFromCallbacksEntity.class, oid);
o.setThrowOnPostUpdate(true);
mutateAndCommit(em, o);
}
public void testPreUpdateExceptionDuringFlushWithExistingFlushedInstance() {
Object oid = insert("new instance");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o =
em.find(ExceptionsFromCallbacksEntity.class, oid);
o.setStringField("foo");
em.flush();
o.setThrowOnPreUpdate(true);
// there's no additional flush work; should not re-invoke the callback
em.flush();
em.getTransaction().commit();
em.close();
}
public void testPreUpdateExceptionDuringCommitWithExistingFlushedInstance(){
Object oid = insert("new instance");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o =
em.find(ExceptionsFromCallbacksEntity.class, oid);
o.setStringField("foo");
em.flush();
o.setThrowOnPreUpdate(true);
// there's no additional flush work; should not re-invoke the callback
em.getTransaction().commit();
em.close();
}
public void testPostUpdateExceptionDuringFlushWithExistingFlushedInstance(){
Object oid = insert("new instance");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o =
em.find(ExceptionsFromCallbacksEntity.class, oid);
o.setStringField("foo");
em.flush();
o.setThrowOnPostUpdate(true);
// no mutations; should not trigger a PostUpdate
em.flush();
em.getTransaction().commit();
em.close();
}
public void testPostUpdateExceptionDuringCommitWithExistingFlushedInstance()
{
Object oid = insert("new instance");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o =
em.find(ExceptionsFromCallbacksEntity.class, oid);
o.setStringField("foo");
em.flush();
// no mutations; should not trigger a PostUpdate
o.setThrowOnPostUpdate(true);
em.getTransaction().commit();
em.close();
}
public void testPostLoadException() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
o.setThrowOnPostLoad(true);
em.persist(o);
em.getTransaction().commit();
Object oid = OpenJPAPersistence.cast(em).getObjectId(o);
em.close();
em = emf.createEntityManager();
em.getTransaction().begin();
try {
em.find(ExceptionsFromCallbacksEntity.class, oid);
fail("find should have failed");
} catch (CallbackTestException cte) {
// transaction should be active but marked for rollback
assertTrue(em.getTransaction().isActive());
assertTrue(em.getTransaction().getRollbackOnly());
} finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
}
public void testPreDeleteException() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPreRemove(true);
try {
em.remove(o);
} catch (CallbackTestException cte) {
// transaction should be active but marked for rollback
assertTrue(em.getTransaction().isActive());
assertTrue(em.getTransaction().getRollbackOnly());
} finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
}
public void testPostDeleteExceptionDuringFlush() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPostRemove(true);
try {
em.remove(o);
} catch (CallbackTestException e) {
em.getTransaction().rollback();
em.close();
fail("PostRemove is being called too soon (before SQL is issued)");
}
flush(em);
}
public void testPostDeleteExceptionDuringCommit() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
o.setThrowOnPostRemove(true);
try {
em.remove(o);
} catch (CallbackTestException e) {
em.getTransaction().rollback();
em.close();
fail("PostRemove is being called too soon (before SQL is issued)");
}
commit(em);
}
public void testPreDeleteExceptionDoubleDelete() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
// this should pass
em.remove(o);
em.flush();
o.setThrowOnPreRemove(true);
// this shoud also pass; no work to do for delete
em.remove(o);
em.getTransaction().commit();
em.close();
}
public void testPostDeleteExceptionDuringFlushDoubleDelete() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
// this should pass
em.remove(o);
em.flush();
o.setThrowOnPostRemove(true);
// this shoud also pass; no work to do for delete
em.remove(o);
em.flush();
em.getTransaction().commit();
em.close();
}
public void testPostDeleteExceptionDuringCommitDoubleDelete() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
em.persist(o);
em.flush();
// this should pass
em.remove(o);
em.flush();
o.setThrowOnPostRemove(true);
// this shoud also pass; no work to do for delete
em.remove(o);
em.getTransaction().commit();
em.close();
}
}