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

This commit is contained in:
Robin Bygrave
2015-08-20 20:46:28 +12:00
parent 46b158a0a0
commit 84190f3c2a
34 changed files with 1642 additions and 84 deletions
@@ -0,0 +1,66 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.ValuePair;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.tests.model.basic.Customer;
import com.avaje.tests.model.basic.Order;
import com.avaje.tests.model.basic.Order.Status;
import org.junit.Test;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class TestDiffHelpInsertSimple extends BaseTestCase {
long firstTime = System.currentTimeMillis() - 10000;
EbeanServer server;
BeanDescriptor<Order> orderDesc;
public TestDiffHelpInsertSimple() {
server = Ebean.getServer(null);
SpiEbeanServer spiServer = (SpiEbeanServer) server;
orderDesc = spiServer.getBeanDescriptor(Order.class);
}
private Order createBaseOrder(EbeanServer server) {
Order order1 = new Order();
order1.setId(12);
order1.setCretime(new Timestamp(firstTime));
order1.setCustomer(server.getReference(Customer.class, 1234));
order1.setStatus(Status.NEW);
//order1.setShipDate(new Date(firstTime));
order1.setOrderDate(new Date(firstTime));
return order1;
}
@Test
public void basic() {
Order order1 = createBaseOrder(server);
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) order1, orderDesc);
assertEquals(4, diff.size());
Set<String> keySet = diff.keySet();
assertTrue(keySet.contains("cretime"));
assertTrue(keySet.contains("status"));
assertTrue(keySet.contains("orderDate"));
assertTrue(keySet.contains("customer.id"));
assertFalse(keySet.contains("shipDate"));
}
}
@@ -0,0 +1,107 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.ValuePair;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.tests.model.embedded.EMain;
import com.avaje.tests.model.embedded.Eembeddable;
import org.junit.Test;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class TestDiffHelpInsertWithEmbedded extends BaseTestCase {
EbeanServer server;
BeanDescriptor<EMain> emainDesc;
public TestDiffHelpInsertWithEmbedded() {
server = Ebean.getServer(null);
SpiEbeanServer spiServer = (SpiEbeanServer) server;
emainDesc = spiServer.getBeanDescriptor(EMain.class);
}
@Test
public void simple() {
EMain emain1 = createEMain();
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) emain1, emainDesc);
assertEquals(3, diff.size());
assertEquals("foo", diff.get("name").getNewValue());
assertEquals(13L, diff.get("version").getNewValue());
ValuePair valuePair = diff.get("embeddable.description");
assertNotNull(valuePair);
assertEquals("bar", valuePair.getNewValue());
assertNull(valuePair.getOldValue());
}
@Test
public void scalarPropertyAsNull() {
EMain emain1 = createEMain();
emain1.setName(null);
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) emain1, emainDesc);
assertEquals(2, diff.size());
assertNull(diff.get("name"));
assertEquals(13L, diff.get("version").getNewValue());
ValuePair valuePair = diff.get("embeddable.description");
assertNotNull(valuePair);
assertEquals("bar", valuePair.getNewValue());
assertNull(valuePair.getOldValue());
}
@Test
public void embeddedAsNull() {
EMain emain1 = createEMain();
emain1.setEmbeddable(null);
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) emain1, emainDesc);
assertEquals(2, diff.size());
assertEquals("foo", diff.get("name").getNewValue());
assertEquals(13L, diff.get("version").getNewValue());
assertNull(diff.get("embeddable.description"));
}
@Test
public void embeddedPropertiesAsNull() {
EMain emain1 = createEMain();
emain1.getEmbeddable().setDescription(null);
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) emain1, emainDesc);
assertEquals(2, diff.size());
assertEquals("foo", diff.get("name").getNewValue());
assertEquals(13L, diff.get("version").getNewValue());
assertNull(diff.get("embeddable.description"));
}
private EMain createEMain() {
EMain emain = new EMain();
emain.setName("foo");
emain.setVersion(13l);
Eembeddable embeddable = new Eembeddable();
embeddable.setDescription("bar");
emain.setEmbeddable(embeddable);
return emain;
}
}
@@ -0,0 +1,159 @@
package com.avaje.tests.changelog;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.EbeanServerFactory;
import com.avaje.ebean.annotation.ChangeLog;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.event.BeanPersistRequest;
import com.avaje.ebean.event.changelog.ChangeLogFilter;
import com.avaje.ebean.event.changelog.ChangeLogListener;
import com.avaje.ebean.event.changelog.ChangeLogPrepare;
import com.avaje.ebean.event.changelog.ChangeLogRegister;
import com.avaje.ebean.event.changelog.ChangeSet;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.tests.model.basic.EBasicChangeLog;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TestChangeLog extends BaseTestCase {
TDChangeLogPrepare changeLogPrepare = new TDChangeLogPrepare();
TDChangeLogListener changeLogListener = new TDChangeLogListener();
TDChangeLogRegister changeLogRegister = new TDChangeLogRegister();
SpiEbeanServer server;
@Before
public void setup() {
server = getServer();
}
@After
public void shutdown() {
server.shutdown(true, false);
}
@Test
public void test() {
EBasicChangeLog bean = new EBasicChangeLog();
bean.setName("logBean");
bean.setShortDescription("hello");
server.save(bean);
bean.setName("ChangedName");
server.save(bean);
server.delete(bean);
}
private SpiEbeanServer getServer() {
ServerConfig config = new ServerConfig();
config.setName("h2other");
config.loadFromProperties();
config.setDdlGenerate(true);
config.setDdlRun(true);
config.setDefaultServer(false);
config.setRegister(false);
config.addClass(EBasicChangeLog.class);
config.setChangeLogPrepare(changeLogPrepare);
config.setChangeLogListener(changeLogListener);
config.setChangeLogRegister(changeLogRegister);
return (SpiEbeanServer) EbeanServerFactory.create(config);
}
class TDChangeLogPrepare implements ChangeLogPrepare {
@Override
public boolean prepare(ChangeSet changes) {
changes.setUserId("appUser1");
changes.setUserIpAddress("1.1.1.1");
return true;
}
}
class TDChangeLogListener implements ChangeLogListener {
ObjectMapper objectMapper = new ObjectMapper();
ChangeSet changes;
/**
*/
public TDChangeLogListener() {
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
@Override
public void log(ChangeSet changes) {
this.changes = changes;
try {
String json = objectMapper.writeValueAsString(changes);
logger.info(json);
ChangeSet changes1 = objectMapper.readValue(json, ChangeSet.class);
assertEquals(changes.getTxnId(), changes1.getTxnId());
assertEquals(changes.getUserId(), changes1.getUserId());
assertEquals(changes.getUserIpAddress(), changes1.getUserIpAddress());
} catch (Exception e) {
e.printStackTrace();
}
}
}
class TDChangeLogRegister implements ChangeLogRegister {
@Override
public ChangeLogFilter getChangeFilter(Class<?> beanType) {
ChangeLog changeLog = beanType.getAnnotation(ChangeLog.class);
if (changeLog != null) {
return new TDFilter();
}
return null;
}
}
/**
* Change log filter that includes all the inserts, updates and deletes.
*/
class TDFilter implements ChangeLogFilter {
/**
* Returns true including all the inserts.
*/
@Override
public boolean includeInsert(BeanPersistRequest<?> insertRequest) {
return true;
}
@Override
public boolean includeUpdate(BeanPersistRequest<?> updateRequest) {
return true;
}
@Override
public boolean includeDelete(BeanPersistRequest<?> deleteRequest) {
return true;
}
}
}
@@ -0,0 +1,120 @@
package com.avaje.tests.model.basic;
import com.avaje.ebean.annotation.ChangeLog;
import com.avaje.ebean.annotation.WhenCreated;
import com.avaje.ebean.annotation.WhenModified;
import com.avaje.ebean.annotation.WhoCreated;
import com.avaje.ebean.annotation.WhoModified;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Version;
import javax.validation.constraints.Size;
import java.sql.Timestamp;
/**
*
*/
@ChangeLog
@Entity
public class EBasicChangeLog {
@Id
Long id;
@Size(max = 20)
String name;
@Size(max = 50)
String shortDescription;
@Size(max = 100)
String longDescription;
@WhoCreated
String whoCreated;
@WhoModified
String whoModified;
@WhenCreated
Timestamp whenCreated;
@WhenModified
Timestamp whenModified;
@Version
Long version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getShortDescription() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getLongDescription() {
return longDescription;
}
public void setLongDescription(String longDescription) {
this.longDescription = longDescription;
}
public String getWhoCreated() {
return whoCreated;
}
public void setWhoCreated(String whoCreated) {
this.whoCreated = whoCreated;
}
public String getWhoModified() {
return whoModified;
}
public void setWhoModified(String whoModified) {
this.whoModified = whoModified;
}
public Timestamp getWhenCreated() {
return whenCreated;
}
public void setWhenCreated(Timestamp whenCreated) {
this.whenCreated = whenCreated;
}
public Timestamp getWhenModified() {
return whenModified;
}
public void setWhenModified(Timestamp whenModified) {
this.whenModified = whenModified;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
}