DATAGRAPH-452 - Adapted to changes in BeanWrapper generics.
Also improved auditing setup by referring to the AuditingHandler via an ObjectFactory (which is causing a break-up of the initialization cycle). Simplified the configuration setup as the handler now works with a MappingContext directly now. Related issues: DATACMNS-468, DATACMNS-365.
This commit is contained in:
@@ -15,95 +15,63 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.config;
|
||||
|
||||
import org.springframework.aop.target.LazyInitTargetSource;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||
import org.springframework.data.config.IsNewAwareAuditingHandlerBeanDefinitionParser;
|
||||
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||
import org.springframework.data.auditing.config.AuditingHandlerBeanDefinitionParser;
|
||||
import org.springframework.data.auditing.config.IsNewAwareAuditingHandlerBeanDefinitionParser;
|
||||
import org.springframework.data.config.ParsingUtils;
|
||||
import org.springframework.data.neo4j.lifecycle.AuditingEventListener;
|
||||
import org.springframework.data.support.IsNewStrategyFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} to register a {@link AuditingEventListener} to transparently set auditing information on
|
||||
* an entity.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Neo4jAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return AuditingEventListener.class;
|
||||
}
|
||||
private static final String MAPPING_CONTEXT = "neo4jMappingContext";
|
||||
|
||||
@Override
|
||||
protected boolean shouldGenerateId() {
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return AuditingEventListener.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
|
||||
*/
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder auditingListenerBuilder) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#shouldGenerateId()
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldGenerateId() {
|
||||
return true;
|
||||
}
|
||||
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
|
||||
if (!registry.containsBeanDefinition(IS_NEW_STRATEGY_FACTORY)) {
|
||||
|
||||
String templateName = MAPPING_CONTEXT;
|
||||
|
||||
if (!registry.containsBeanDefinition(MAPPING_CONTEXT)) {
|
||||
templateName = resolveMappingContextRef(element);
|
||||
}
|
||||
|
||||
createIsNewStrategyFactoryBeanDefinition(templateName, parserContext, element);
|
||||
}
|
||||
|
||||
BeanDefinitionParser isNewStrategyParser = new IsNewAwareAuditingHandlerBeanDefinitionParser(IS_NEW_STRATEGY_FACTORY);
|
||||
BeanDefinition isNewStrategyBeanDefinition = isNewStrategyParser.parse(element, parserContext);
|
||||
|
||||
// TODO
|
||||
// BeanDefinitionBuilder lazyInitTS = BeanDefinitionBuilder.genericBeanDefinition(LazyInitTargetSource.class);
|
||||
// lazyInitTS.addPropertyValue("targetBeanName", isNewStrategyBeanDefinition);
|
||||
// lazyInitTS.addPropertyValue("targetClass", IsNewStrategyFactory.class.getName());
|
||||
//
|
||||
// auditingListenerBuilder.addConstructorArgValue(lazyInitTS);
|
||||
auditingListenerBuilder.addConstructorArgValue(isNewStrategyBeanDefinition);
|
||||
}
|
||||
|
||||
static String resolveMappingContextRef(Element element) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
|
||||
*/
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder auditingListenerBuilder) {
|
||||
|
||||
String ctxRef = element.getAttribute("mapping-context-ref");
|
||||
|
||||
if (StringUtils.hasText(ctxRef)) {
|
||||
return ctxRef;
|
||||
if (!StringUtils.hasText(ctxRef)) {
|
||||
ctxRef = MAPPING_CONTEXT;
|
||||
}
|
||||
|
||||
return MAPPING_CONTEXT;
|
||||
}
|
||||
|
||||
private String createIsNewStrategyFactoryBeanDefinition(String mappingContextRef, ParserContext context,
|
||||
Element element) {
|
||||
AuditingHandlerBeanDefinitionParser auditingHandlerParser = new IsNewAwareAuditingHandlerBeanDefinitionParser(
|
||||
ctxRef);
|
||||
auditingHandlerParser.parse(element, parserContext);
|
||||
|
||||
BeanDefinitionBuilder mappingContextStrategyFactoryBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(MappingContextIsNewStrategyFactory.class);
|
||||
mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
|
||||
BeanComponentDefinitionBuilder builder = new BeanComponentDefinitionBuilder(element, context);
|
||||
context.registerBeanComponent(builder.getComponent(mappingContextStrategyFactoryBuilder, IS_NEW_STRATEGY_FACTORY));
|
||||
|
||||
return IS_NEW_STRATEGY_FACTORY;
|
||||
}
|
||||
|
||||
|
||||
static final String MAPPING_CONTEXT = "neo4jMappingContext";
|
||||
static final String IS_NEW_STRATEGY_FACTORY = "isNewStrategyFactory";
|
||||
auditingListenerBuilder.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(
|
||||
auditingHandlerParser.getResolvedBeanName(), parserContext.extractSource(element)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.lifecycle;
|
||||
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.springframework.data.auditing.AuditingHandler;
|
||||
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Event listener to populate auditing related fields on an entity about to be saved.
|
||||
@@ -28,14 +28,14 @@ import org.springframework.data.auditing.IsNewAwareAuditingHandler;
|
||||
*/
|
||||
public class AuditingEventListener implements ApplicationListener<BeforeSaveEvent<Object>> {
|
||||
|
||||
private final IsNewAwareAuditingHandler auditingHandler;
|
||||
private final ObjectFactory<IsNewAwareAuditingHandler> auditingHandler;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AuditingEventListener} using the given {@link org.springframework.data.mapping.context.MappingContext} and {@link AuditingHandler}.
|
||||
*
|
||||
* @param auditingHandler must not be {@literal null}.
|
||||
*/
|
||||
public AuditingEventListener(IsNewAwareAuditingHandler auditingHandler) {
|
||||
public AuditingEventListener(ObjectFactory<IsNewAwareAuditingHandler> auditingHandler) {
|
||||
|
||||
Assert.notNull(auditingHandler, "IsNewAwareAuditingHandler must not be null!");
|
||||
this.auditingHandler = auditingHandler;
|
||||
@@ -48,6 +48,6 @@ public class AuditingEventListener implements ApplicationListener<BeforeSaveEven
|
||||
public void onApplicationEvent(BeforeSaveEvent<Object> event) {
|
||||
|
||||
Object entity = event.getEntity();
|
||||
auditingHandler.markAudited(entity);
|
||||
auditingHandler.getObject().markAudited(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ class Neo4jPersistentPropertyImpl extends AnnotationBasedPersistentProperty<Neo4
|
||||
@Override
|
||||
public void setValue(Object entity, Object newValue) {
|
||||
|
||||
BeanWrapper<PersistentEntity<Object,?>,Object> wrapper = BeanWrapper.create(entity, null);
|
||||
BeanWrapper<Object> wrapper = BeanWrapper.create(entity, null);
|
||||
wrapper.setProperty(this, newValue);
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ class Neo4jPersistentPropertyImpl extends AnnotationBasedPersistentProperty<Neo4
|
||||
@Override
|
||||
public Object getValueFromEntity(Object entity, final MappingPolicy mappingPolicy) {
|
||||
|
||||
BeanWrapper<PersistentEntity<Object,?>, Object> wrapper = BeanWrapper.create(entity, null);
|
||||
BeanWrapper<Object> wrapper = BeanWrapper.create(entity, null);
|
||||
return wrapper.getProperty(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ public class Neo4jEntityConverterImpl<T,S extends PropertyContainer> implements
|
||||
@Override
|
||||
public <R extends T> R loadEntity(R entity, S source, MappingPolicy mappingPolicy, Neo4jPersistentEntityImpl<R> persistentEntity, final Neo4jTemplate template) {
|
||||
if (mappingPolicy.shouldLoad()) {
|
||||
final BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper = BeanWrapper.<Neo4jPersistentEntity<R>, R>create(entity, conversionService);
|
||||
final BeanWrapper<R> wrapper = BeanWrapper.create(entity, conversionService);
|
||||
sourceStateTransmitter.copyPropertiesFrom(wrapper, source, persistentEntity,mappingPolicy, template);
|
||||
// 6) handle cascading fetches
|
||||
cascadeFetch(persistentEntity, wrapper, mappingPolicy, template);
|
||||
@@ -121,7 +121,7 @@ public class Neo4jEntityConverterImpl<T,S extends PropertyContainer> implements
|
||||
return requestedType.isAssignableFrom(storedType.getType());
|
||||
}
|
||||
|
||||
private <R extends T> void cascadeFetch(Neo4jPersistentEntityImpl<R> persistentEntity, final BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper, final MappingPolicy policy, final Neo4jTemplate template) {
|
||||
private <R extends T> void cascadeFetch(Neo4jPersistentEntityImpl<R> persistentEntity, final BeanWrapper<R> wrapper, final MappingPolicy policy, final Neo4jTemplate template) {
|
||||
persistentEntity.doWithAssociations(new AssociationHandler<Neo4jPersistentProperty>() {
|
||||
@Override
|
||||
public void doWithAssociation(Association<Neo4jPersistentProperty> association) {
|
||||
@@ -140,7 +140,7 @@ public class Neo4jEntityConverterImpl<T,S extends PropertyContainer> implements
|
||||
});
|
||||
}
|
||||
|
||||
private <R> Object getProperty(BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper, Neo4jPersistentProperty property) {
|
||||
private <R> Object getProperty(BeanWrapper<R> wrapper, Neo4jPersistentProperty property) {
|
||||
try {
|
||||
return wrapper.getProperty(property);
|
||||
} catch (Exception e) {
|
||||
@@ -158,7 +158,7 @@ public class Neo4jEntityConverterImpl<T,S extends PropertyContainer> implements
|
||||
return;
|
||||
}
|
||||
|
||||
final BeanWrapper<Neo4jPersistentEntity<T>, T> wrapper = BeanWrapper.<Neo4jPersistentEntity<T>, T>create(source, conversionService);
|
||||
final BeanWrapper<T> wrapper = BeanWrapper.create(source, conversionService);
|
||||
if (sink == null) {
|
||||
sink = entityStateHandler.useOrCreateState(source,sink, annotationProvidedRelationshipType ); // todo handling of changed state
|
||||
entityStateHandler.setPersistentState(source, sink);
|
||||
|
||||
@@ -55,7 +55,7 @@ public class Neo4jEntityFetchHandler {
|
||||
if (property.getTypeInformation().isCollectionLike()) {
|
||||
List<Object> replacement = new ArrayList<Object>();
|
||||
for (Object inner : ((Iterable) value)) {
|
||||
final BeanWrapper<Neo4jPersistentEntity<Object>, Object> innerWrapper = BeanWrapper.<Neo4jPersistentEntity<Object>, Object>create(inner, conversionService);
|
||||
final BeanWrapper<Object> innerWrapper = BeanWrapper.create(inner, conversionService);
|
||||
final PropertyContainer state = entityStateHandler.getPersistentState(inner);
|
||||
fetchValue(innerWrapper, state, persistentEntity, mappingPolicy, template);
|
||||
replacement.add(inner);
|
||||
@@ -63,14 +63,14 @@ public class Neo4jEntityFetchHandler {
|
||||
}
|
||||
return replacement;
|
||||
} else {
|
||||
final BeanWrapper<Neo4jPersistentEntity<Object>, Object> innerWrapper = BeanWrapper.<Neo4jPersistentEntity<Object>, Object>create(value, conversionService);
|
||||
final BeanWrapper<Object> innerWrapper = BeanWrapper.create(value, conversionService);
|
||||
final PropertyContainer state = entityStateHandler.getPersistentState(value);
|
||||
fetchValue(innerWrapper, state, persistentEntity, mappingPolicy, template);
|
||||
// sourceStateTransmitter.copyPropertiesFrom(innerWrapper, entityStateHandler.<S>getPersistentState(value), persistentEntity);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
public void fetchValue(final BeanWrapper<Neo4jPersistentEntity<Object>, Object> wrapper, PropertyContainer source, Neo4jPersistentEntity<Object> persistentEntity, final MappingPolicy mappingPolicy, final Neo4jTemplate template) {
|
||||
public void fetchValue(final BeanWrapper<Object> wrapper, PropertyContainer source, Neo4jPersistentEntity<Object> persistentEntity, final MappingPolicy mappingPolicy, final Neo4jTemplate template) {
|
||||
if (persistentEntity.isNodeEntity()) {
|
||||
nodeStateTransmitter.copyPropertiesFrom(wrapper, (Node) source,persistentEntity, mappingPolicy, template);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class SourceStateTransmitter<S extends PropertyContainer> {
|
||||
this.entityStateFactory = entityStateFactory;
|
||||
}
|
||||
|
||||
public <R> R copyPropertiesFrom(final BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper, S source, Neo4jPersistentEntity<R> persistentEntity, final MappingPolicy mappingPolicy, final Neo4jTemplate template) {
|
||||
public <R> R copyPropertiesFrom(final BeanWrapper<R> wrapper, S source, Neo4jPersistentEntity<R> persistentEntity, final MappingPolicy mappingPolicy, final Neo4jTemplate template) {
|
||||
final R entity = wrapper.getBean();
|
||||
final EntityState<S> entityState = entityStateFactory.getEntityState(entity, false, template);
|
||||
entityState.setPersistentState(source);
|
||||
@@ -64,13 +64,13 @@ public class SourceStateTransmitter<S extends PropertyContainer> {
|
||||
return entity;
|
||||
}
|
||||
|
||||
private <R> void setEntityStateValue(Neo4jPersistentProperty property, EntityState<S> entityState, BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper, final MappingPolicy mappingPolicy) {
|
||||
private <R> void setEntityStateValue(Neo4jPersistentProperty property, EntityState<S> entityState, BeanWrapper<R> wrapper, final MappingPolicy mappingPolicy) {
|
||||
if (!entityState.isWritable(property)) return;
|
||||
final Object value = getProperty(wrapper, property);
|
||||
entityState.setValue(property, value, mappingPolicy);
|
||||
}
|
||||
|
||||
private <R> Object getProperty(BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper, Neo4jPersistentProperty property) {
|
||||
private <R> Object getProperty(BeanWrapper<R> wrapper, Neo4jPersistentProperty property) {
|
||||
try {
|
||||
return wrapper.getProperty(property);
|
||||
} catch (Exception e) {
|
||||
@@ -78,7 +78,7 @@ public class SourceStateTransmitter<S extends PropertyContainer> {
|
||||
}
|
||||
}
|
||||
|
||||
public <R> void setProperty(BeanWrapper<Neo4jPersistentEntity<R>, ?> wrapper, Neo4jPersistentProperty property, Object value) {
|
||||
public <R> void setProperty(BeanWrapper<?> wrapper, Neo4jPersistentProperty property, Object value) {
|
||||
try {
|
||||
wrapper.setProperty(property,value);
|
||||
} catch (Exception e) {
|
||||
@@ -86,13 +86,13 @@ public class SourceStateTransmitter<S extends PropertyContainer> {
|
||||
}
|
||||
}
|
||||
|
||||
private <R> Object copyEntityStatePropertyValue(Neo4jPersistentProperty property, EntityState<S> nodeState, BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper, final MappingPolicy mappingPolicy) {
|
||||
private <R> Object copyEntityStatePropertyValue(Neo4jPersistentProperty property, EntityState<S> nodeState, BeanWrapper<R> wrapper, final MappingPolicy mappingPolicy) {
|
||||
final Object value = DoReturn.unwrap(nodeState.getValue(property, mappingPolicy));
|
||||
setProperty(wrapper, property, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public <R> void copyPropertiesTo(final BeanWrapper<Neo4jPersistentEntity<R>, R> wrapper, S target, Neo4jPersistentEntity<R> persistentEntity, MappingPolicy mappingPolicy, final Neo4jTemplate template) {
|
||||
public <R> void copyPropertiesTo(final BeanWrapper<R> wrapper, S target, Neo4jPersistentEntity<R> persistentEntity, MappingPolicy mappingPolicy, final Neo4jTemplate template) {
|
||||
final Transaction tx = template.getGraphDatabase().beginTx();
|
||||
try {
|
||||
final EntityState<S> entityState = entityStateFactory.getEntityState(wrapper.getBean(), false, template);
|
||||
|
||||
@@ -15,66 +15,69 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.config;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.lifecycle.BeforeSaveEvent;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
@Ignore
|
||||
/**
|
||||
* Integration tests for Neo4j auditing.
|
||||
*
|
||||
* @author Michael Hunger
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AuditingIntegrationTests {
|
||||
|
||||
/**
|
||||
* @see DATAGRAPH-328
|
||||
*/
|
||||
@Test
|
||||
public void enablesAuditingAndSetsPropertiesAccordingly() throws InterruptedException {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("auditing.xml", getClass());
|
||||
runTest(context);
|
||||
context.close();
|
||||
runTest(new ClassPathXmlApplicationContext("auditing.xml", getClass())).close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAGRAPH-328
|
||||
*/
|
||||
@Test
|
||||
public void enablesAuditingWithBeanConfigAndSetsPropertiesAccordingly() throws InterruptedException {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("auditing-bean.xml", getClass());
|
||||
runTest(context);
|
||||
context.close();
|
||||
runTest(new ClassPathXmlApplicationContext("auditing-bean.xml", getClass())).close();
|
||||
}
|
||||
|
||||
private void runTest(ApplicationContext context) throws InterruptedException {
|
||||
Entity entity = new Entity();
|
||||
BeforeSaveEvent<Entity> event = new BeforeSaveEvent<Entity>(this,entity);
|
||||
context.publishEvent(event);
|
||||
private <T extends ApplicationEventPublisher> T runTest(T context) throws InterruptedException {
|
||||
|
||||
assertThat(entity.created, is(notNullValue()));
|
||||
assertThat(entity.modified, is(entity.created));
|
||||
Thread.sleep(10);
|
||||
entity.id = 1L;
|
||||
event = new BeforeSaveEvent<Entity>(this,entity);
|
||||
context.publishEvent(event);
|
||||
Entity entity = new Entity();
|
||||
BeforeSaveEvent<Entity> event = new BeforeSaveEvent<Entity>(this, entity);
|
||||
context.publishEvent(event);
|
||||
|
||||
assertThat(entity.created, is(notNullValue()));
|
||||
assertThat(entity.modified, is(not(entity.created)));
|
||||
}
|
||||
assertThat(entity.created, is(notNullValue()));
|
||||
assertThat(entity.modified, is(entity.created));
|
||||
Thread.sleep(10);
|
||||
entity.id = 1L;
|
||||
event = new BeforeSaveEvent<Entity>(this, entity);
|
||||
context.publishEvent(event);
|
||||
|
||||
@NodeEntity
|
||||
class Entity {
|
||||
assertThat(entity.created, is(notNullValue()));
|
||||
assertThat(entity.modified, is(not(entity.created)));
|
||||
|
||||
@CreatedDate
|
||||
DateTime created;
|
||||
return context;
|
||||
}
|
||||
|
||||
@LastModifiedDate
|
||||
DateTime modified;
|
||||
@NodeEntity
|
||||
public static class Entity {
|
||||
|
||||
@GraphId
|
||||
Long id;
|
||||
@GraphId Long id;
|
||||
@CreatedDate DateTime created;
|
||||
@LastModifiedDate DateTime modified;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.lifecycle;
|
||||
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
|
||||
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
|
||||
@@ -47,14 +46,14 @@ public class AuditingEventListenerUnitTests {
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
Neo4jMappingContext mappingContext = new Neo4jMappingContext();
|
||||
factory = new MappingContextIsNewStrategyFactory(mappingContext);
|
||||
handler = spy(new IsNewAwareAuditingHandler(new Neo4jMappingContext()));
|
||||
listener = new AuditingEventListener(new ObjectFactory<IsNewAwareAuditingHandler>() {
|
||||
|
||||
handler = spy(new IsNewAwareAuditingHandler(factory));
|
||||
doNothing().when(handler).markCreated(Mockito.any(Object.class));
|
||||
doNothing().when(handler).markModified(Mockito.any(Object.class));
|
||||
|
||||
listener = new AuditingEventListener(handler);
|
||||
@Override
|
||||
public IsNewAwareAuditingHandler getObject() throws BeansException {
|
||||
return handler;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -66,7 +65,7 @@ public class AuditingEventListenerUnitTests {
|
||||
public void triggersCreationMarkForObjectWithEmptyId() {
|
||||
|
||||
Sample sample = new Sample();
|
||||
listener.onApplicationEvent(new BeforeSaveEvent<Object>(this,sample));
|
||||
listener.onApplicationEvent(new BeforeSaveEvent<Object>(this, sample));
|
||||
|
||||
verify(handler, times(1)).markCreated(sample);
|
||||
verify(handler, times(0)).markModified(any(Sample.class));
|
||||
@@ -77,16 +76,15 @@ public class AuditingEventListenerUnitTests {
|
||||
|
||||
Sample sample = new Sample();
|
||||
sample.id = "id";
|
||||
listener.onApplicationEvent(new BeforeSaveEvent<Object>(this,sample));
|
||||
listener.onApplicationEvent(new BeforeSaveEvent<Object>(this, sample));
|
||||
|
||||
verify(handler, times(0)).markCreated(any(Sample.class));
|
||||
verify(handler, times(1)).markModified(sample);
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
@NodeEntity
|
||||
static class Sample {
|
||||
|
||||
@GraphId
|
||||
String id;
|
||||
@GraphId String id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.2.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<neo4j:config graphDatabaseService="graphDatabaseService" base-package="org.springframework.data.neo4j.config"/>
|
||||
<neo4j:config graphDatabaseService="graphDatabaseService"
|
||||
base-package="org.springframework.data.neo4j.config" />
|
||||
|
||||
<bean class="org.springframework.data.neo4j.lifecycle.AuditingEventListener" autowire="constructor" />
|
||||
|
||||
<bean id="auditingHandler" class="org.springframework.data.auditing.IsNewAwareAuditingHandler">
|
||||
<constructor-arg ref="neo4jMappingContext" />
|
||||
</bean>
|
||||
|
||||
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase"
|
||||
destroy-method="shutdown" />
|
||||
|
||||
<bean class="org.springframework.data.neo4j.lifecycle.AuditingEventListener">
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.data.auditing.IsNewAwareAuditingHandler">
|
||||
<constructor-arg ref="isNewStrategyFactory"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase" destroy-method="shutdown"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.2.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<neo4j:config graphDatabaseService="graphDatabaseService" base-package="org.springframework.data.neo4j.config.model" />
|
||||
<neo4j:config graphDatabaseService="graphDatabaseService" base-package="org.springframework.data.neo4j.config" />
|
||||
|
||||
<neo4j:auditing />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user