mandubian/siena — Issue #14: Lifecycle annotations: @PreInsert not called on batch insert 
Author: henricpersson
Created: 2011-12-27 10:20:55+00:00
State: open

We have started to use the Lifecycle annotations provided with Siena and found a couple of issues with how it is implemented. One of them is that methods annotated with @PreInsert aren't called on insertions via the Model.batch() method.

Below is a testcase demonstrating the bug. Note that there are a couple of test cases. For this bug, look for the **preInsertShouldWorkOnBatchInsert()** test method. I'll file another bug for the other test cases that fail.

```java
package siena.lifecycle.test;

import java.io.IOException;
import java.util.Date;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig;

import siena.Generator;
import siena.Id;
import siena.Model;
import siena.PersistenceManager;
import siena.PersistenceManagerFactory;
import siena.core.PersistenceManagerLifeCycleWrapper;
import siena.core.lifecycle.PreInsert;
import siena.core.lifecycle.PreUpdate;
import siena.gae.GaePersistenceManager;

public class LifeCycleTest {

/**
* A simple model class with lifecycle annotations
*
* @author henper
*
*/
public static class LifeCycleEntity extends Model {

@Id(Generator.AUTO_INCREMENT)
public Long id;
public Date created;
public Date updated;

public @PreInsert void onInsert() {
created = new Date();
}

public @PreUpdate @PreInsert void onUpdate() {
updated = new Date();
}
}

@Test
public void preInsertShouldWorkOnBatchInsert() {
// If you are storing multiple entities at once, a batch insert is handy:
LifeCycleEntity one = new LifeCycleEntity();
LifeCycleEntity two = new LifeCycleEntity();
Model.batch(LifeCycleEntity.class).insert(one, two);

// It is expected that the @PreInsert is called once for each entity, before inserting them:
Assert.assertNotNull("The \"created\" date was not updated for entity \"one\"", one.created);
Assert.assertNotNull("The \"created\" date was not updated for entity \"two\"", two.created);
}

@Test
public void preUpdateAndPreInsertShouldBeCalledOnSave() {
LifeCycleEntity one = new LifeCycleEntity();
one.save();
Assert.assertNotNull("The \"created\" date was not updated on save()", one.created);
Assert.assertNotNull("The \"updated\" date was not updated on save()", one.updated);
}

@Test
public void preInsertShouldBeCalledOnInsert() {
LifeCycleEntity one = new LifeCycleEntity();
one.insert();
Assert.assertNotNull("The \"created\" date was not updated on insert()", one.created);
Assert.assertNotNull("The \"updated\" date was not updated on insert()", one.updated);
}

@Test
public void preUpdateShouldBeCalledOnUpdate() {
LifeCycleEntity one = new LifeCycleEntity();
one.insert();
one.update();
Assert.assertNotNull("The \"created\" date was not updated on update()", one.created);
Assert.assertNotNull("The \"updated\" date was not updated on update()", one.updated);
}

@Before
public void setUp() throws Exception {
helper.setUp();
}

@After
public void tearDown() throws Exception {
helper.tearDown();
}

@Before
public void enableLifeCycleSupport() {
PersistenceManager pm = new GaePersistenceManager();
pm = new PersistenceManagerLifeCycleWrapper(pm);
pm.init(null);
PersistenceManagerFactory.install(pm, LifeCycleEntity.class);
}
private final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig(), new LocalTaskQueueTestConfig());
}

```