Author: echatellier Date: 2013-07-23 16:49:44 +0200 (Tue, 23 Jul 2013) New Revision: 2779 Url: http://nuiton.org/projects/topia/repository/revisions/2779 Log: fixes #2787: Cascade save is not managed by composition Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java 2013-07-22 23:57:38 UTC (rev 2778) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java 2013-07-23 14:49:44 UTC (rev 2779) @@ -555,8 +555,7 @@ // we must call getServiceRegistry on factory to get a working one ServiceRegistry serviceRegistryInit = ((SessionFactoryImplementor) hibernateFactory).getServiceRegistry(); EventListenerRegistry eventListenerRegistry = serviceRegistryInit.getService(EventListenerRegistry.class); - TopiaFiresSupport.TopiaHibernateEvent listener = - new TopiaFiresSupport.TopiaHibernateEvent(this); + TopiaFiresSupport.TopiaHibernateEvent listener = new TopiaFiresSupport.TopiaHibernateEvent(this); eventListenerRegistry.appendListeners(EventType.PRE_INSERT, listener); eventListenerRegistry.appendListeners(EventType.PRE_LOAD, listener); eventListenerRegistry.appendListeners(EventType.PRE_UPDATE, listener); @@ -565,6 +564,9 @@ eventListenerRegistry.appendListeners(EventType.POST_LOAD, listener); eventListenerRegistry.appendListeners(EventType.POST_UPDATE, listener); eventListenerRegistry.appendListeners(EventType.POST_DELETE, listener); + + // following listeners must be called before hibernate + eventListenerRegistry.prependListeners(EventType.SAVE_UPDATE, listener); } } return hibernateFactory; Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java 2013-07-22 23:57:38 UTC (rev 2778) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java 2013-07-23 14:49:44 UTC (rev 2779) @@ -36,8 +36,10 @@ import java.util.Set; import org.apache.commons.collections.map.IdentityMap; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.event.spi.PostDeleteEvent; import org.hibernate.event.spi.PostDeleteEventListener; @@ -47,6 +49,8 @@ import org.hibernate.event.spi.PostLoadEventListener; import org.hibernate.event.spi.PostUpdateEvent; import org.hibernate.event.spi.PostUpdateEventListener; +import org.hibernate.event.spi.PreCollectionUpdateEvent; +import org.hibernate.event.spi.PreCollectionUpdateEventListener; import org.hibernate.event.spi.PreDeleteEvent; import org.hibernate.event.spi.PreDeleteEventListener; import org.hibernate.event.spi.PreInsertEvent; @@ -55,6 +59,8 @@ import org.hibernate.event.spi.PreLoadEventListener; import org.hibernate.event.spi.PreUpdateEvent; import org.hibernate.event.spi.PreUpdateEventListener; +import org.hibernate.event.spi.SaveOrUpdateEvent; +import org.hibernate.event.spi.SaveOrUpdateEventListener; import org.nuiton.topia.TopiaContext; import org.nuiton.topia.TopiaException; import org.nuiton.topia.TopiaVetoException; @@ -544,7 +550,7 @@ PostInsertEventListener, PreLoadEventListener, PostLoadEventListener, PreUpdateEventListener, PostUpdateEventListener, PreDeleteEventListener, - PostDeleteEventListener { + PostDeleteEventListener, SaveOrUpdateEventListener { private static final long serialVersionUID = 7303593133642169218L; @@ -622,9 +628,18 @@ TopiaContextImplementor context = getContext(rootContext, event .getSession()); if (context != null && event.getEntity() instanceof TopiaEntity) { - context.getFiresSupport().fireOnPreCreate(context, - (TopiaEntity) event.getEntity(), event.getState()); + TopiaEntity entity = (TopiaEntity) event.getEntity(); + context.getFiresSupport().fireOnPreCreate(context, entity, event.getState()); + + // when using composition, hibernate will persist entities by him self + // entity must have an id in this case. + if (StringUtils.isBlank(entity.getTopiaId())) { + if (log.isDebugEnabled()) { + log.debug("Adding topia id on entity " + entity.getClass().getSimpleName()); + } + } } + return false; } @@ -722,6 +737,31 @@ // context.getIndexEnginImplementor().recordForIndexation(id, null); // } } + + @Override + public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { + try { + // this event is called when hibernate try to persist entities + // using cascade (save) + TopiaContextImplementor context = getContext(rootContext, event.getSession()); + // warning, event.getEntity() return null here :( + if (event.getObject() instanceof TopiaEntity) { + TopiaEntity entity = (TopiaEntity)event.getObject(); + if (StringUtils.isBlank(entity.getTopiaId())) { + if (log.isDebugEnabled()) { + log.debug("Adding topiaId into entity " + entity.getClass()); + } + // FIXME echatellier 20130713 : hack to find interface for current entity class + // #newTopiaId only accept interface + Class entityInterface = Class.forName(event.getEntityName().replace("Impl", "")); + String topiaId = context.getTopiaIdFactory().newTopiaId(entityInterface, entity); + entity.setTopiaId(topiaId); + } + } + } catch (ClassNotFoundException ex) { + throw new HibernateException("Can't set id", ex); + } + } } /**