persistence@glassfish.java.net

Re: PreRemove ConcurrentModificationException

From: Markus Fuchs <Markus.Fuchs_at_Sun.COM>
Date: Thu, 14 Jun 2007 16:14:31 -0700
Hi Greg,

Please add the mappedby attribute in the OneToMany annotation:

In ArticleGroup:
 @OneToMany(cascade=CascadeType.ALL, mappedBy="articleGroup")
 @OrderBy("position ASC")
 private List<ArticlePlacement> articlePlacements = new ArrayList<ArticlePlacement>();

W/o mappedBy, this relationship is taken as an uni-directional OneToMany relation mapped to the jointable article_group_article_placement. Is that intended?

-- markus.

Greg Ederer wrote:
Hi Markus,

When I remove the @PreRemove from both Article and ArticlePlacement, and em.remove(articlePlacement), I get the following stack trace:

Removing class com.acadept.model.article.ArticlePlacement with id 1
Local Exception Stack: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b50a-beta3 (06/13/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on table "article_placement" violates foreign key constraint "fk_article_group_article_placement_articleplacements_id" on table "article_group_article_placement"
 Detail: Key (id)=(1) is still referenced from table "article_group_article_placement".
Error Code: 0
Call: DELETE FROM article_placement WHERE (ID = ?)
       bind => [1]
Query: DeleteObjectQuery(com.acadept.model.ArticlePlacement[id=1])
       at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:311)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:654)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:703)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:492)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:214)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:205)
       at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:130)
       at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.deleteObjectForWrite(DatabaseQueryMechanism.java:258)
       at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeCommit(DeleteObjectQuery.java:98)
       at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWrite(DatabaseQueryMechanism.java:335)
       at oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:111)
       at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:628)
       at oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:555)
       at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:138)
       at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:125)
       at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:110)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2233)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:952)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
       at oracle.toplink.essentials.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:338)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1047)
       at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:403)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1126)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:2443)
       at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:202)
       at oracle.toplink.essentials.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:131)
       at oracle.toplink.essentials.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:91)
       at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:419)
       at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
       at com.sun.enterprise.distributedtx.UserTransactionImpl.commit(UserTransactionImpl.java:197)
       at com.acadept.web.controller.JSONFormController.handleRequestInternal(JSONFormController.java:129)
       at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
       at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
       at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
       at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:774)
       at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:460)
       at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:425)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
       at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:135)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:229)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
       at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:39)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288)
       at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:268)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:631)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:562)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:803)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:339)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:261)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:212)
       at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
       at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "article_placement" violates foreign key constraint "fk_article_group_article_placement_articleplacements_id" on table "article_group_article_placement"
 Detail: Key (id)=(1) is still referenced from table "article_group_article_placement".
       at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1548)
       at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1316)
       at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:191)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:351)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:305)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:647)
       ... 93 more
Local Exception Stack: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b50a-beta3 (06/13/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on table "article_placement" violates foreign key constraint "fk_article_group_article_placement_articleplacements_id" on table "article_group_article_placement"
 Detail: Key (id)=(1) is still referenced from table "article_group_article_placement".
Error Code: 0
Call: DELETE FROM article_placement WHERE (ID = ?)
       bind => [1]
Query: DeleteObjectQuery(com.acadept.model.ArticlePlacement[id=1])
       at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:311)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:654)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:703)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:492)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:214)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:205)
       at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:130)
       at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.deleteObjectForWrite(DatabaseQueryMechanism.java:258)
       at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeCommit(DeleteObjectQuery.java:98)
       at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWrite(DatabaseQueryMechanism.java:335)
       at oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:111)
       at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:628)
       at oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:555)
       at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:138)
       at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:125)
       at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:110)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2233)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:952)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
       at oracle.toplink.essentials.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:338)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1047)
       at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:403)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1126)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:2443)
       at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:202)
       at oracle.toplink.essentials.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:131)
       at oracle.toplink.essentials.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:91)
       at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:419)
       at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
       at com.sun.enterprise.distributedtx.UserTransactionImpl.commit(UserTransactionImpl.java:197)
       at com.acadept.web.controller.JSONFormController.handleRequestInternal(JSONFormController.java:129)
       at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
       at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
       at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
       at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:774)
       at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:460)
       at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:425)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
       at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:135)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:229)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
       at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:39)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288)
       at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:268)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:631)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:562)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:803)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:339)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:261)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:212)
       at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
       at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "article_placement" violates foreign key constraint "fk_article_group_article_placement_articleplacements_id" on table "article_group_article_placement"
 Detail: Key (id)=(1) is still referenced from table "article_group_article_placement".
       at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1548)
       at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1316)
       at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:191)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:351)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:305)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:647)
       ... 93 more
StandardWrapperValve[acadept]: PWC1406: Servlet.service() for servlet acadept threw exception
javax.transaction.RollbackException: Transaction marked for rollback.
       at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:440)
       at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
       at com.sun.enterprise.distributedtx.UserTransactionImpl.commit(UserTransactionImpl.java:197)
       at com.acadept.web.controller.JSONFormController.handleRequestInternal(JSONFormController.java:129)
       at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
       at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
       at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
       at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:774)
       at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:460)
       at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:425)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
       at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:135)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:229)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
       at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:39)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288)
       at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:268)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:631)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:562)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:803)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:339)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:261)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:212)
       at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
       at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)

When  I em.remove(article) without @PreRemoves, I get:

Removing class com.acadept.model.article.Article with id 3
Local Exception Stack: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b50a-beta3 (06/13/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on table "article_placement" violates foreign key constraint "fk_article_group_article_placement_articleplacements_id" on table "article_group_article_placement"
 Detail: Key (id)=(1) is still referenced from table "article_group_article_placement".
Error Code: 0
Call: DELETE FROM article_placement WHERE (ID = ?)
       bind => [1]
Query: DeleteObjectQuery(com.acadept.model.ArticlePlacement[id=1])
       at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:311)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:654)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:703)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:492)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:214)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:205)
       at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:130)
       at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.deleteObjectForWrite(DatabaseQueryMechanism.java:258)
       at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeCommit(DeleteObjectQuery.java:98)
       at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWrite(DatabaseQueryMechanism.java:335)
       at oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:111)
       at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:628)
       at oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:555)
       at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:138)
       at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:125)
       at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:110)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2233)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:952)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
       at oracle.toplink.essentials.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:338)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1047)
       at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:403)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1126)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:2443)
       at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:202)
       at oracle.toplink.essentials.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:131)
       at oracle.toplink.essentials.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:91)
       at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:419)
       at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
       at com.sun.enterprise.distributedtx.UserTransactionImpl.commit(UserTransactionImpl.java:197)
       at com.acadept.web.controller.JSONFormController.handleRequestInternal(JSONFormController.java:129)
       at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
       at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
       at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
       at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:774)
       at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:460)
       at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:425)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
       at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:135)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:229)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
       at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:39)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288)
       at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:268)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:631)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:562)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:803)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:339)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:261)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:212)
       at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
       at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "article_placement" violates foreign key constraint "fk_article_group_article_placement_articleplacements_id" on table "article_group_article_placement"
 Detail: Key (id)=(1) is still referenced from table "article_group_article_placement".
       at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1548)
       at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1316)
       at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:191)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:351)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:305)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:647)
       ... 93 more
Local Exception Stack: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b50a-beta3 (06/13/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on table "article_placement" violates foreign key constraint "fk_article_group_article_placement_articleplacements_id" on table "article_group_article_placement"
 Detail: Key (id)=(1) is still referenced from table "article_group_article_placement".
Error Code: 0
Call: DELETE FROM article_placement WHERE (ID = ?)
       bind => [1]
Query: DeleteObjectQuery(com.acadept.model.ArticlePlacement[id=1])
       at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:311)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:654)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:703)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:492)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:214)
       at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:205)
       at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:130)
       at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.deleteObjectForWrite(DatabaseQueryMechanism.java:258)
       at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeCommit(DeleteObjectQuery.java:98)
       at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWrite(DatabaseQueryMechanism.java:335)
       at oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:111)
       at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:628)
       at oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:555)
       at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:138)
       at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:125)
       at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:110)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2233)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:952)
       at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
       at oracle.toplink.essentials.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:338)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1047)
       at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:403)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1126)
       at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:2443)
       at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:202)
       at oracle.toplink.essentials.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:131)
       at oracle.toplink.essentials.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:91)
       at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:419)
       at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
       at com.sun.enterprise.distributedtx.UserTransactionImpl.commit(UserTransactionImpl.java:197)
       at com.acadept.web.controller.JSONFormController.handleRequestInternal(JSONFormController.java:129)
       at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
       at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
       at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
       at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:774)
       at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:460)
       at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:425)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
       at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:135)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:229)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
       at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:39)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288)
       at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:268)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:631)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:562)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:803)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:339)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:261)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:212)
       at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
       at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "article_placement" violates foreign key constraint "fk_article_group_article_placement_articleplacements_id" on table "article_group_article_placement"
 Detail: Key (id)=(1) is still referenced from table "article_group_article_placement".
       at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1548)
       at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1316)
       at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:191)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:351)
       at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:305)
       at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:647)
       ... 93 more
StandardWrapperValve[acadept]: PWC1406: Servlet.service() for servlet acadept threw exception
javax.transaction.RollbackException: Transaction marked for rollback.
       at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:440)
       at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
       at com.sun.enterprise.distributedtx.UserTransactionImpl.commit(UserTransactionImpl.java:197)
       at com.acadept.web.controller.JSONFormController.handleRequestInternal(JSONFormController.java:129)
       at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
       at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
       at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
       at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:774)
       at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:460)
       at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:425)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
       at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
       at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:135)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:229)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
       at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
       at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
       at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:39)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288)
       at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
       at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
       at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
       at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
       at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:268)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:631)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:562)
       at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:803)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:339)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:261)
       at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:212)
       at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
       at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)


Restoring the @PreRemove callbacks to both classes resolves these problems.

Also, I upgraded to v2b50a.

Thanks for the tip on removing the return value from merge!

Cheers,

Greg

Markus Fuchs wrote:
Hi Greg,

I can't see, why you should get a foreign key violation removing an ArticlePlacement, since ArticlePlacement owns the the relationships to Article and ArticleGroup. To only other relationship is a uni-directional OneToMany between Article and ArticleGroup. But neither Articles nor ArticleGroups are removed, correct?

BTW, in

      utx.begin();
      em.merge(o);
      em.joinTransaction();
      em.remove(o);
      utx.commit();

you should call the remove operation on the managed copy returned by em.merge(o)

Thanks,

-- markus.
Where javaType is com.acadept.model.article.ArticlePlacement.

Greg Ederer wrote:
Markus Fuchs wrote:
Hi Greg,

That sounds like a bug to me. Could you send me your pojos and a small snipplet of your application code as a test case?

You are talking about em.remove(article) and no @PreRemove in ArticlePlacement resulting in a foreign key violation, correct?

Actually, I get the fk violation when I em.remove(articlePlacement) w/o the @PreRemove.  Does this still sound like a bug, or is it just my incorrect way of doing things?

Code below.

Cheers,

Greg

In my servlet:

       Object o = em.find(javaType, id);
       responseMap.put("javaType", javaType);
       responseMap.put("id", id);
       utx.begin();
       em.merge(o);
       em.joinTransaction();
       em.remove(o);
       utx.commit();


/*
* Article.java
*
* Created on May 7, 2007, 2:15 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package com.acadept.model.article;

import com.acadept.model.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PreRemove;
import javax.persistence.SequenceGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
* Entity class Article
* * @author gregederer
*/
@Entity
public class Article implements Serializable
{
 @Id
 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ARTICLE_SEQ_GENERATOR")
 @SequenceGenerator(name = "ARTICLE_SEQ_GENERATOR", sequenceName = "ARTICLE_ID_SEQ")
 private Long id;
 
 @ManyToOne
 private ArticleCategory articleCategory;
 
 @OneToMany(mappedBy = "article", cascade=CascadeType.ALL)
 private List<ArticlePlacement> articlePlacements = new ArrayList<ArticlePlacement>();
 
 @Column(name="lead_in_image")
 private String leadInImage;
 
 private String title;
 
 private String subTitle;
 
 @Column(name="lead_in", columnDefinition="text")
 private String leadIn;
 
 @Column(columnDefinition="text")
 private String body;
 
 @OneToOne
 private AppUser poster;
 
 @Column(name="publication_date")
 @Temporal(TemporalType.DATE)
 private Date createdDate;
 
 /** Creates a new instance of Article */
 public Article()
 {
 }

 /**
  * Gets the id of this Article.
  * @return the id
  */
 public Long getId()
 {
   return this.id;
 }

 /**
  * Sets the id of this Article to the specified value.
  * @param id the new id
  */
 public void setId(Long id)
 {
   this.id = id;
 }

 /**
  * Returns a hash code value for the object.  This implementation computes   * a hash code value based on the id fields in this object.
  * @return a hash code value for this object.
  */
 @Override
 public int hashCode()
 {
   int hash = 0;
   hash += (this.getId() != null ? this.getId().hashCode() : 0);
   return hash;
 }

 /**
  * Determines whether another object is equal to this Article.  The result is   * <code>true</code> if and only if the argument is not null and is a Article object that   * has the same id field values as this object.
  * @param object the reference object with which to compare
  * @return <code>true</code> if this object is the same as the argument;
  * <code>false</code> otherwise.
  */
 @Override
 public boolean equals(Object object)
 {
   // TODO: Warning - this method won't work in the case the id fields are not set
   if (!(object instanceof Article)) {
     return false;
   }
   Article other = (Article)object;
      // If both are the same object, return true
   if(this == other)
   {
     return true;
   }
      // If both objects have ids, compare their ids
   if(this.getId() != null && other.getId() != null)
   {
     // If their ids are equal, return true
     if(this.getId().equals(other.getId()))
     {
       return true;
     }
     // Otherwise, return false
     else
     {
       return false;
     }
   }
      // If one or both do not have ids, compare their 'natural keys'
   if(this.getTitle() != null && this.getTitle().equals(other.getTitle())
      && this.getCreatedDate() != null && this.getCreatedDate().equals(other.getCreatedDate())
      && this.getPoster() != null && this.getPoster().equals(other.getPoster())
      )
   {
     return true;
   }
      return false;
 }

 /**
  * Returns a string representation of the object.  This implementation constructs   * that representation based on the id fields.
  * @return a string representation of the object.
  */
 @Override
 public String toString()
 {
   return "com.acadept.model.Article[id=" + getId() + "]";
 }

 public ArticleCategory getArticleCategory()
 {
   return articleCategory;
 }

 public void setArticleCategory(ArticleCategory articleCategory)
 {
   this.articleCategory = articleCategory;
   articleCategory.addArticle(this);
 }

 public String getTitle()
 {
   return title;
 }

 public void setTitle(String title)
 {
   this.title = title;
 }

 public String getSubTitle()
 {
   return subTitle;
 }

 public void setSubTitle(String subTitle)
 {
   this.subTitle = subTitle;
 }

 public String getLeadIn()
 {
   return leadIn;
 }

 public void setLeadIn(String leadIn)
 {
   this.leadIn = leadIn;
 }

 public String getBody()
 {
   return body;
 }

 public void setBody(String body)
 {
   this.body = body;
 }

 public AppUser getPoster()
 {
   return poster;
 }

 public void setPoster(AppUser poster)
 {
   this.poster = poster;
 }

 public Date getCreatedDate()
 {
   return createdDate;
 }

 public void setCreatedDate(Date createdDate)
 {
   this.createdDate = createdDate;
 }

 public String getLeadInImage()
 {
   return leadInImage;
 }

 public void setLeadInImage(String leadInImage)
 {
   this.leadInImage = leadInImage;
 }

 public List<ArticlePlacement> getArticlePlacements()
 {
   return articlePlacements;
 }

 public void setArticlePlacements(List<ArticlePlacement> articlePlacements)
 {
   this.articlePlacements = articlePlacements;
 }
 
 public void addArticlePlacement(ArticlePlacement articlePlacement)
 {
   if(this.getArticlePlacements().contains(articlePlacement))
   {
     return;
   }
      getArticlePlacements().add(articlePlacement);
   articlePlacement.setArticle(this);
 }
 
 public void removeArticlePlacement(ArticlePlacement articlePlacement)
 {
   getArticlePlacements().remove(articlePlacement);
   articlePlacement.setArticle(null);
 }
 
 @PreRemove
 public void beforeRemove()
 {
   List<ArticlePlacement> articlePlacements = getArticlePlacements();
   for(ArticlePlacement ap : articlePlacements)
   {
     ap.setArticle(null);
   }
 }
}


/*
* ArticlePlacement.java
*
* Created on May 7, 2007, 2:32 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package com.acadept.model.article;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.PreRemove;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
* Entity class ArticlePlacement
*
* @author gregederer
*/
@Entity
@Table(name="article_placement")
public class ArticlePlacement implements Serializable
{
 @Id
 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ARTICLE_PLACEMENT_SEQ_GENERATOR")
 @SequenceGenerator(name = "ARTICLE_PLACEMENT_SEQ_GENERATOR", sequenceName = "ARTICLE_PLACEMENT_ID_SEQ")
 private Long id;
 
 @ManyToOne
 private Article article;
 
 @ManyToOne
 private ArticleGroup articleGroup;
 
 @Temporal(value = TemporalType.TIMESTAMP)
 @Column(name="order_position")
 private Date position;
 
 @Temporal(TemporalType.TIMESTAMP)
 private Date startRunDate;
 
 @Temporal(TemporalType.TIMESTAMP)
 private Date endRunDate;
 
 /** Creates a new instance of ArticlePlacement */
 public ArticlePlacement()
 {
 }
 
 /**
  * Gets the id of this ArticlePlacement.
  * @return the id
  */
 public Long getId()
 {
   return this.id;
 }
 
 /**
  * Sets the id of this ArticlePlacement to the specified value.
  * @param id the new id
  */
 public void setId(Long id)
 {
   this.id = id;
 }
 
 /**
  * Returns a hash code value for the object.  This implementation computes
  * a hash code value based on the id fields in this object.
  * @return a hash code value for this object.
  */
 @Override
 public int hashCode()
 {
   int hash = 0;
   hash += (this.getId() != null ? this.getId().hashCode() : 0);
   return hash;
 }
 
 /**
  * Determines whether another object is equal to this ArticlePlacement.  The result is
  * <code>true</code> if and only if the argument is not null and is a ArticlePlacement object that
  * has the same id field values as this object.
  * @param object the reference object with which to compare
  * @return <code>true</code> if this object is the same as the argument;
  * <code>false</code> otherwise.
  */
 @Override
 public boolean equals(Object object)
 {
   if (!(object instanceof ArticlePlacement))
   {
     return false;
   }
   ArticlePlacement other = (ArticlePlacement)object;
      // If both are the same object, return true
   if(this == other)
   {
     return true;
   }
      // If both objects have ids, compare their ids
   if(this.getId() != null && other.getId() != null)
   {
     // If their ids are equal, return true
     if(this.getId().equals(other.getId()))
     {
       return true;
     }
     // Otherwise, return false
     else
     {
       return false;
     }
   }
      // If one or both do not have ids, compare their 'natural keys'
   if(this.getArticle() != null && this.getArticle().equals(other.getArticle())
           && this.getArticleGroup() != null && this.getArticleGroup().equals(other.getArticleGroup())
           )
   {
     return true;
   }
      return false;
 }
 
 /**
  * Returns a string representation of the object.  This implementation constructs
  * that representation based on the id fields.
  * @return a string representation of the object.
  */
 @Override
 public String toString()
 {
   return "com.acadept.model.ArticlePlacement[id=" + getId() + "]";
 }
 
 public Article getArticle()
 {
   return article;
 }
 
 public void setArticle(Article article)
 {
   this.article = article;
      if(article != null)
   {
     article.addArticlePlacement(this);
   }
 }
 
 public ArticleGroup getArticleGroup()
 {
   return articleGroup;
 }
 
 public void setArticleGroup(ArticleGroup articleGroup)
 {
   this.articleGroup = articleGroup;
      if(articleGroup != null)
   {
     articleGroup.addArticlePlacement(this);
   }
 }
 
 public Date getPosition()
 {
   return position;
 }
 
 public void setPosition(Date position)
 {
   this.position = position;
 }
 
 public Date getStartRunDate()
 {
   return startRunDate;
 }
 
 public void setStartRunDate(Date startRunDate)
 {
   this.startRunDate = startRunDate;
 }
 
 public Date getEndRunDate()
 {
   return endRunDate;
 }
 
 public void setEndRunDate(Date endRunDate)
 {
   this.endRunDate = endRunDate;
 }
 
 @PreRemove
 public void beforeRemove()
 {
   getArticleGroup().removeArticlePlacement(this);
   if(getArticle() != null)
   {
     getArticle().removeArticlePlacement(this);
   }
 }
}


/*
* ArticleGroup.java
*
* Created on May 7, 2007, 2:27 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package com.acadept.model.article;

import com.acadept.model.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

/**
* Entity class ArticleGroup
* * @author gregederer
*/
@Entity
@Table(name="article_group")
public class ArticleGroup implements Serializable
{
 private static Logger logger = Logger.getLogger(ContentGroup.class.getName());
 
 @Id
 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ARTICLE_GROUP_SEQ_GENERATOR")
 @SequenceGenerator(name = "ARTICLE_GROUP_SEQ_GENERATOR", sequenceName = "ARTICLE_GROUP_ID_SEQ")
 private Long id;
 
 @Column(name="content_name", unique=true)
 private String name;
 
 @Column(columnDefinition="text")
 private String description;
 
 @OneToMany(cascade=CascadeType.ALL)
 @OrderBy("position ASC")
 private List<ArticlePlacement> articlePlacements = new ArrayList<ArticlePlacement>();

 /**
  * Gets the id of this ArticleGroup.
  * @return the id
  */
 public Long getId()
 {
   return this.id;
 }

 /**
  * Sets the id of this ArticleGroup to the specified value.
  * @param id the new id
  */
 public void setId(Long id)
 {
   this.id = id;
 }

 /**
  * Returns a hash code value for the object.  This implementation computes   * a hash code value based on the id fields in this object.
  * @return a hash code value for this object.
  */
 @Override
 public int hashCode()
 {
   int hash = 0;
   hash += (this.getId() != null ? this.getId().hashCode() : 0);
   return hash;
 }

 /**
  * Determines whether another object is equal to this ArticleGroup.  The result is   * <code>true</code> if and only if the argument is not null and is a ArticleGroup object that   * has the same id field values as this object.
  * @param object the reference object with which to compare
  * @return <code>true</code> if this object is the same as the argument;
  * <code>false</code> otherwise.
  */
 @Override
 public boolean equals(Object object)
 {
   // TODO: Warning - this method won't work in the case the id fields are not set
   if (!(object instanceof ArticleGroup)) {
     return false;
   }
   ArticleGroup other = (ArticleGroup)object;
      // If both are the same object, return true
   if(this == other)
   {
     return true;
   }
      // If both objects have ids, compare their ids
   if(this.getId() != null && other.getId() != null)
   {
     // If their ids are equal, return true
     if(this.getId().equals(other.getId()))
     {
       return true;
     }
     // Otherwise, return false
     else
     {
       return false;
     }
   }
      // If one or both do not have ids, compare their 'natural keys'
   if(this.getName() != null && this.getName().equals(other.getName())
      )
   {
     return true;
   }
      return false;
 }

 /**
  * Returns a string representation of the object.  This implementation constructs   * that representation based on the id fields.
  * @return a string representation of the object.
  */
 @Override
 public String toString()
 {
   return "com.acadept.model.ArticleGroup[id=" + getId() + "]";
 }

 public static Logger getLogger()
 {
   return logger;
 }

 public static void setLogger(Logger aLogger)
 {
   logger = aLogger;
 }

 public String getName()
 {
   return name;
 }

 public void setName(String name)
 {
   this.name = name;
 }

 public String getDescription()
 {
   return description;
 }

 public void setDescription(String description)
 {
   this.description = description;
 }

 public List<ArticlePlacement> getArticlePlacements()
 {
   return articlePlacements;
 }

 public void setArticlePlacements(List<ArticlePlacement> articlePlacements)
 {
   this.articlePlacements = articlePlacements;
 }
 
 public void addArticlePlacement(ArticlePlacement articlePlacement)
 {
   if(this.getArticlePlacements().contains(articlePlacement))
   {
     return;
   }
      getArticlePlacements().add(articlePlacement);
   articlePlacement.setArticleGroup(this);
 }
 
 public void removeArticlePlacement(ArticlePlacement articlePlacement)
 {
   getArticlePlacements().remove(articlePlacement);
   articlePlacement.setArticleGroup(null);
 }
}


Thanks,

-- markus.

Greg Ederer wrote:
Markus Fuchs wrote:
Hi Greg,

Do you get a foreign key violation w/o using @PreRemove callbacks in your pojos? Are you using a current glassfish build?

Hi Markus,

Yes.  When I em.remove() an ArticlePlacement without the @PreRemove, I get a PSQLException (I'm using PostgreSQL) with a foreign key constraint violation message.

I'm using v2b50.

Thanks for the reply.

Cheers,

Greg
Thanks,

-- markus.

Greg Ederer wrote:
I managed to get this working by adding the following to Article:

 @PreRemove
 public void beforeRemove()
 {
   List<ArticlePlacement> articlePlacements = getArticlePlacements();
   for(ArticlePlacement ap : articlePlacements)
   {
     ap.setArticle(null);
   }
 }

And in ArticlePlacement:

 @PreRemove
 public void beforeRemove()
 {
   getArticleGroup().removeArticlePlacement(this);
   if(getArticle() != null)
   {
     getArticle().removeArticlePlacement(this);
   }
 }

I have a feeling this is not the best way to handle this (and, I'm guessing that I'll feel like a dummy when I find out the correct way to do this, because it will be pretty obvious).

Any advice welcome.

Cheers,

Greg

Greg Ederer wrote:
Oops!  Accidentally hit send.  Please ignore previous post.

I have a model containing three entity classes: Article, ArticleGroup and ArticlePlacement.  An ArticleGroup contains zero or more ArticlePlacement objects.  Each ArticlePlacement wraps an Article (ArticlePlacement also has a start run date and an end run date, which allows me to run an article in multiple groups during different periods).

So, in Article, I have:

 @OneToMany(mappedBy = "article", cascade=CascadeType.ALL)
 private List<ArticlePlacement> articlePlacements = new ArrayList<ArticlePlacement>();

In ArticleGroup, I have:

 @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
 @OrderBy("position ASC")
 private List<ArticlePlacement> articlePlacements = new ArrayList<ArticlePlacement>();

And, in ArticlePlacement, I have:

 @ManyToOne
 private Article article;

 @ManyToOne
 private ArticleGroup articleGroup;

 @PreRemove
 public void beforeRemove()
 {
   getArticleGroup().removeArticlePlacement(this);
   getArticle().removeArticlePlacement(this);
 }

When I EntityManager.remove() an Article, I get a java.util.ConcurrentModificationException due to the getArticle().removeArticlePlacement(this) in @PreRemove, above.  But, if I comment this out, I get a "violates foreign key" PSQLException.

Can someone tell me how to deal with this situation correctly?

Thanks!

Greg