#390 - ENH: Add Change log mechanism for easy fine grained logging of insert, update, delete activity.

This adds default implementations for register,filter, prepare and log of the change sets.
This commit is contained in:
Robin Bygrave
2015-08-22 12:10:30 +12:00
parent 31099f6dda
commit fe8a32ea18
25 changed files with 764 additions and 19 deletions
@@ -0,0 +1,44 @@
package com.avaje.ebean.bean;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.tests.model.basic.Customer;
import com.avaje.tests.model.basic.ResetBasicData;
import org.junit.Test;
import java.sql.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class EntityBeanInterceptTest extends BaseTestCase {
@Test
public void testHasDirtyProperty() throws Exception {
ResetBasicData.reset();
List<Customer> list = Ebean.find(Customer.class).findList();
Set<String> propertyNames = new HashSet<String>();
propertyNames.add("name");
propertyNames.add("status");
Customer customer = list.get(0);
EntityBeanIntercept ebi = ((EntityBean)customer)._ebean_getIntercept();
assertFalse(ebi.hasDirtyProperty(propertyNames));
customer.setAnniversary(new Date(System.currentTimeMillis()));
assertFalse(ebi.hasDirtyProperty(propertyNames));
customer.setStatus(Customer.Status.ACTIVE);
assertTrue(ebi.hasDirtyProperty(propertyNames));
}
}
@@ -22,7 +22,7 @@ public class BeanFindControllerTest extends BaseTestCase {
ServerConfig config = new ServerConfig();
config.setName("h2other");
config.setName("h2otherfind");
config.loadFromProperties();
config.setDdlGenerate(true);
config.setDdlRun(true);
@@ -0,0 +1,30 @@
package com.avaje.ebeaninternal.server.changelog;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.text.json.JsonContext;
import org.junit.Test;
import java.io.StringWriter;
public class BulkJsonBuilderTest extends BaseTestCase {
Helper helper = new Helper();
@Test
public void testToJson() throws Exception {
JsonContext jsonContext = Ebean.getDefaultServer().json();
BulkJsonBuilder builder = new BulkJsonBuilder(jsonContext, "changelog2", "changelog2");
StringWriter buffer = new StringWriter();
builder.writeJson(helper.createChangeSet("ABCD", 10), buffer);
System.out.println(buffer.toString());
buffer = new StringWriter();
builder.writeJson(helper.createChangeSet("ABCD-2", 15), buffer);
System.out.println(buffer.toString());
}
}
@@ -0,0 +1,40 @@
package com.avaje.ebeaninternal.server.changelog;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.event.changelog.ChangeLogFilter;
import com.avaje.tests.model.basic.Address;
import com.avaje.tests.model.basic.Contact;
import com.avaje.tests.model.basic.Country;
import com.avaje.tests.model.basic.Customer;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class DefaultChangeLogRegisterTest extends BaseTestCase {
DefaultChangeLogRegister register = new DefaultChangeLogRegister();
@Test
public void test() {
assertNull(register.getChangeFilter(Address.class));
ChangeLogFilter changeFilter = register.getChangeFilter(Customer.class);
DefaultChangeLogRegister.UpdateFilter updateFilter = (DefaultChangeLogRegister.UpdateFilter)changeFilter;
assertFalse(updateFilter.includeInserts);
assertThat(updateFilter.updateProperties).containsExactly("name", "status");
changeFilter = register.getChangeFilter(Contact.class);
DefaultChangeLogRegister.BasicFilter contactFilter = (DefaultChangeLogRegister.BasicFilter)changeFilter;
assertTrue(contactFilter.includeInserts);
changeFilter = register.getChangeFilter(Country.class);
DefaultChangeLogRegister.BasicFilter countryFilter = (DefaultChangeLogRegister.BasicFilter)changeFilter;
assertFalse(countryFilter.includeInserts);
}
}
@@ -0,0 +1,26 @@
package com.avaje.ebeaninternal.server.changelog;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.event.changelog.ChangeSet;
import org.junit.Test;
public class ElasticChangeLogListenerTest extends BaseTestCase {
Helper helper = new Helper();
@Test
public void test() {
ElasticChangeLogListener changeLogListener = new ElasticChangeLogListener();
EbeanServer defaultServer = Ebean.getDefaultServer();
changeLogListener.configure(defaultServer.getPluginApi());
ChangeSet changeSet = helper.createChangeSet("INT-001", 13);
changeLogListener.log(changeSet);
}
}
@@ -0,0 +1,68 @@
package com.avaje.ebeaninternal.server.changelog;
import com.avaje.ebean.ValuePair;
import com.avaje.ebean.event.changelog.BeanChange;
import com.avaje.ebean.event.changelog.ChangeSet;
import com.avaje.ebean.event.changelog.ChangeType;
import com.avaje.ebean.event.changelog.TxnState;
import org.jetbrains.annotations.NotNull;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class Helper {
public ChangeSet createChangeSet(String txnId, long startId) {
ChangeSet cs = new ChangeSet();
cs.setTxnId(txnId);
cs.setTxnState(TxnState.COMMITTED);
cs.setTxnBatch(0);
cs.setSource("myApp");
cs.setUserId("user234");
cs.setUserIpAddress("123.4.5.6");
cs.setUserContext("user defined input");
List<BeanChange> changes = cs.getChanges();
changes.add(createInsert(startId));
changes.add(createUpdate(startId));
changes.add(createDelete(startId));
return cs;
}
@NotNull
private BeanChange createInsert(long startId) {
Map<String, ValuePair> values = new LinkedHashMap<String, ValuePair>();
values.put("name", new ValuePair("rob", null));
values.put("modified", new ValuePair(new Timestamp(System.currentTimeMillis()), null));
BeanChange bean = new BeanChange("mytable", startId+1, ChangeType.INSERT, null);
bean.setValues(values);
return bean;
}
@NotNull
private BeanChange createUpdate(long startId) {
Map<String, ValuePair> values = new LinkedHashMap<String, ValuePair>();
values.put("name", new ValuePair("jim", "steve"));
values.put("nowHasVal", new ValuePair("wasNull", null));
values.put("nowNull", new ValuePair(null, "hadVal"));
values.put("modified", new ValuePair(new Timestamp(System.currentTimeMillis()), null));
BeanChange bean = new BeanChange("mytable", startId+2, ChangeType.UPDATE, null);
bean.setValues(values);
return bean;
}
@NotNull
private BeanChange createDelete(long startId) {
return new BeanChange("mytable", startId+3, ChangeType.DELETE, new HashMap<String, ValuePair>());
}
}
@@ -10,8 +10,10 @@ import javax.persistence.OneToMany;
import javax.persistence.Version;
import com.avaje.ebean.annotation.CacheStrategy;
import com.avaje.ebean.annotation.ChangeLog;
import com.avaje.ebean.annotation.CreatedTimestamp;
@ChangeLog
@Entity
@CacheStrategy(naturalKey="email")
public class Contact {
@@ -7,10 +7,12 @@ import javax.validation.constraints.Size;
import com.avaje.ebean.annotation.CacheStrategy;
import com.avaje.ebean.annotation.CacheTuning;
import com.avaje.ebean.annotation.ChangeLog;
/**
* Country entity bean.
*/
@ChangeLog(excludeInserts = true)
@CacheStrategy(readOnly=true,warmingQuery="order by name")
@CacheTuning(maxSize=500)
@Entity
@@ -1,5 +1,6 @@
package com.avaje.tests.model.basic;
import com.avaje.ebean.annotation.ChangeLog;
import com.avaje.ebean.annotation.EnumValue;
import com.avaje.ebean.annotation.JsonIgnore;
import com.avaje.ebean.annotation.Where;
@@ -20,6 +21,7 @@ import java.util.concurrent.locks.ReentrantLock;
/**
* Customer entity bean.
*/
@ChangeLog(excludeInserts = true, updatesThatInclude = {"name","status"})
@Entity
@Table(name = "o_customer")
public class Customer extends BasicDomain {
@@ -15,7 +15,7 @@ import java.sql.Timestamp;
/**
*
*/
@ChangeLog
@ChangeLog(updatesThatInclude = {"name","shortDescription"})
@Entity
public class EBasicChangeLog {
@@ -22,6 +22,7 @@ import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlType;
import com.avaje.ebean.annotation.ChangeLog;
import com.avaje.ebean.annotation.Formula;
import com.avaje.ebean.annotation.WhenCreated;
import com.avaje.ebean.annotation.Where;
@@ -29,6 +30,7 @@ import com.avaje.ebean.annotation.Where;
/**
* Order entity bean.
*/
@ChangeLog
@Entity
@Table(name = "o_order")
public class Order implements Serializable {