DATAKV-91 - Add support for sending application events.
We now allow definition of event types to be published via the application context. Original pull request: #5.
This commit is contained in:
committed by
Thomas Darimont
parent
a8a37d4a32
commit
07b3a1547c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -101,4 +101,12 @@ public interface KeyValueAdapter extends DisposableBean {
|
||||
* @return
|
||||
*/
|
||||
long count(KeyValueQuery<?> query, Serializable keyspace);
|
||||
|
||||
/**
|
||||
* Check if values from the given keyspace are contained in the underlying key-value store.
|
||||
*
|
||||
* @param keyspace
|
||||
* @return true if {@literal keyspace} already present in adapter.
|
||||
*/
|
||||
boolean hasKeyspace(Serializable keyspace);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,14 +20,22 @@ import static org.springframework.data.keyvalue.core.KeySpaceUtils.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent;
|
||||
import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
|
||||
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
@@ -35,6 +43,7 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -42,8 +51,9 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class KeyValueTemplate implements KeyValueOperations {
|
||||
public class KeyValueTemplate implements KeyValueOperations, ApplicationContextAware {
|
||||
|
||||
private static final PersistenceExceptionTranslator DEFAULT_PERSISTENCE_EXCEPTION_TRANSLATOR = new KeyValuePersistenceExceptionTranslator();
|
||||
|
||||
@@ -51,6 +61,8 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
private final ConcurrentHashMap<Class<?>, String> keySpaceCache = new ConcurrentHashMap<Class<?>, String>();
|
||||
private final MappingContext<? extends PersistentEntity<?, ? extends PersistentProperty<?>>, ? extends PersistentProperty<?>> mappingContext;
|
||||
private final IdentifierGenerator identifierGenerator;
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
private final Set<KeyValueEvent.Type> eventTypesToPublish = new HashSet<KeyValueEvent.Type>(4);
|
||||
private PersistenceExceptionTranslator exceptionTranslator = DEFAULT_PERSISTENCE_EXCEPTION_TRANSLATOR;
|
||||
|
||||
/**
|
||||
@@ -109,22 +121,26 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
Assert.notNull(id, "Id for object to be inserted must not be null!");
|
||||
Assert.notNull(objectToInsert, "Object to be inserted must not be null!");
|
||||
|
||||
final String keyspace = resolveKeySpace(objectToInsert.getClass());
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.beforeInsert(this, keyspace, id, objectToInsert));
|
||||
|
||||
execute(new KeyValueCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInKeyValue(KeyValueAdapter adapter) {
|
||||
|
||||
String typeKey = resolveKeySpace(objectToInsert.getClass());
|
||||
|
||||
if (adapter.contains(id, typeKey)) {
|
||||
if (adapter.contains(id, keyspace)) {
|
||||
throw new DuplicateKeyException(String.format(
|
||||
"Cannot insert existing object with id %s!. Please use update.", id));
|
||||
}
|
||||
|
||||
adapter.put(id, objectToInsert, typeKey);
|
||||
adapter.put(id, objectToInsert, keyspace);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.afterInsert(this, keyspace, id, objectToInsert));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -156,14 +172,20 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
Assert.notNull(id, "Id for object to be inserted must not be null!");
|
||||
Assert.notNull(objectToUpdate, "Object to be updated must not be null!");
|
||||
|
||||
final String keyspace = resolveKeySpace(objectToUpdate.getClass());
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.beforeUpdate(this, keyspace, id, objectToUpdate));
|
||||
|
||||
execute(new KeyValueCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInKeyValue(KeyValueAdapter adapter) {
|
||||
adapter.put(id, objectToUpdate, resolveKeySpace(objectToUpdate.getClass()));
|
||||
adapter.put(id, objectToUpdate, keyspace);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.afterUpdate(this, keyspace, id, objectToUpdate));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -209,13 +231,17 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
Assert.notNull(id, "Id for object to be inserted must not be null!");
|
||||
Assert.notNull(type, "Type to fetch must not be null!");
|
||||
|
||||
return execute(new KeyValueCallback<T>() {
|
||||
final String keyspace = resolveKeySpace(type);
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.beforeGet(this, keyspace, id));
|
||||
|
||||
T result = execute(new KeyValueCallback<T>() {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T doInKeyValue(KeyValueAdapter adapter) {
|
||||
|
||||
Object result = adapter.get(id, resolveKeySpace(type));
|
||||
Object result = adapter.get(id, keyspace);
|
||||
|
||||
if (result == null || getKeySpace(type) == null || typeCheck(type, result)) {
|
||||
return (T) result;
|
||||
@@ -224,6 +250,10 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.afterGet(this, keyspace, id, result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -235,17 +265,21 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
|
||||
Assert.notNull(type, "Type to delete must not be null!");
|
||||
|
||||
final String typeKey = resolveKeySpace(type);
|
||||
final String keyspace = resolveKeySpace(type);
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.beforeDelete(this, keyspace));
|
||||
|
||||
execute(new KeyValueCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInKeyValue(KeyValueAdapter adapter) {
|
||||
|
||||
adapter.deleteAllOf(typeKey);
|
||||
adapter.deleteAllOf(keyspace);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.afterDelete(this, keyspace));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -272,14 +306,22 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
Assert.notNull(id, "Id for object to be inserted must not be null!");
|
||||
Assert.notNull(type, "Type to delete must not be null!");
|
||||
|
||||
return execute(new KeyValueCallback<T>() {
|
||||
final String keyspace = resolveKeySpace(type);
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.beforeDelete(this, keyspace, id));
|
||||
|
||||
T result = execute(new KeyValueCallback<T>() {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T doInKeyValue(KeyValueAdapter adapter) {
|
||||
return (T) adapter.delete(id, resolveKeySpace(type));
|
||||
return (T) adapter.delete(id, keyspace);
|
||||
}
|
||||
});
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.afterDelete(this, keyspace, id, result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -416,14 +458,37 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
this.exceptionTranslator = exceptionTranslator;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
eventPublisher = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the event types to publish via {@link ApplicationEventPublisher}.
|
||||
*
|
||||
* @param eventTypesToPublish use {@literal null} or {@link Collections#emptySet()} to disable publishing.
|
||||
*/
|
||||
public void setEventTypesToPublish(Set<KeyValueEvent.Type> eventTypesToPublish) {
|
||||
|
||||
this.eventTypesToPublish.clear();
|
||||
|
||||
if (!CollectionUtils.isEmpty(eventTypesToPublish)) {
|
||||
this.eventTypesToPublish.addAll(eventTypesToPublish);
|
||||
}
|
||||
}
|
||||
|
||||
protected String resolveKeySpace(Class<?> type) {
|
||||
|
||||
Class<?> userClass = ClassUtils.getUserClass(type);
|
||||
|
||||
String potentialAlias = keySpaceCache.get(userClass);
|
||||
String potentialKeySpace = keySpaceCache.get(userClass);
|
||||
|
||||
if (potentialAlias != null) {
|
||||
return potentialAlias;
|
||||
if (potentialKeySpace != null) {
|
||||
return potentialKeySpace;
|
||||
}
|
||||
|
||||
String keySpaceString = null;
|
||||
@@ -450,4 +515,15 @@ public class KeyValueTemplate implements KeyValueOperations {
|
||||
DataAccessException translatedException = exceptionTranslator.translateExceptionIfPossible(e);
|
||||
return translatedException != null ? translatedException : e;
|
||||
}
|
||||
|
||||
private void potentiallyPublishEvent(KeyValueEvent event) {
|
||||
|
||||
if (eventPublisher == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventTypesToPublish.contains(event.getType()) || eventTypesToPublish.contains(KeyValueEvent.Type.ANY)) {
|
||||
eventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.keyvalue.core.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* {@link KeyValueEvent} gets published for operations executed by eg.
|
||||
* {@link org.springframework.data.keyvalue.core.KeyValueTemplate}. Use the {@link #getType()} to determine which event
|
||||
* has been emitted.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
* @param <T>
|
||||
*/
|
||||
public class KeyValueEvent extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = -7128527253428193044L;
|
||||
|
||||
public enum Type {
|
||||
ANY, BEFORE_INSERT, AFTER_INSERT, BEFORE_UPDATE, AFTER_UPDATE, BEFORE_DELETE, AFTER_DELETE, BEFORE_GET, AFTER_GET
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
private final String keyspace;
|
||||
private final Serializable id;
|
||||
private final Object value;
|
||||
|
||||
protected KeyValueEvent(Object source, Type type, String keyspace, Serializable id, Object value) {
|
||||
|
||||
super(source);
|
||||
this.type = type;
|
||||
this.keyspace = keyspace;
|
||||
this.id = id;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Type} of event. Never {@literal null}.
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return affected keyspace. Never {@literal null}.
|
||||
*/
|
||||
public String getKeyspace() {
|
||||
return keyspace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
public Serializable getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KeyValueEvent [type=" + type + ", keyspace=" + keyspace + ", id=" + id + "]";
|
||||
}
|
||||
|
||||
public static GetEvent beforeGet(Object source, String keyspace, Serializable id) {
|
||||
return new GetEvent(source, Type.BEFORE_GET, keyspace, id, null);
|
||||
}
|
||||
|
||||
public static GetEvent afterGet(Object source, String keyspace, Serializable id, Object value) {
|
||||
return new GetEvent(source, Type.AFTER_GET, keyspace, id, value);
|
||||
}
|
||||
|
||||
public static InsertEvent beforeInsert(Object source, String keyspace, Serializable id, Object value) {
|
||||
return new InsertEvent(source, Type.BEFORE_INSERT, keyspace, id, value);
|
||||
}
|
||||
|
||||
public static InsertEvent afterInsert(Object source, String keyspace, Serializable id, Object value) {
|
||||
return new InsertEvent(source, Type.AFTER_INSERT, keyspace, id, value);
|
||||
}
|
||||
|
||||
public static UpdateEvent beforeUpdate(Object source, String keyspace, Serializable id, Object value) {
|
||||
return new UpdateEvent(source, Type.BEFORE_UPDATE, keyspace, id, value);
|
||||
}
|
||||
|
||||
public static UpdateEvent afterUpdate(Object source, String keyspace, Serializable id, Object value) {
|
||||
return new UpdateEvent(source, Type.AFTER_UPDATE, keyspace, id, value);
|
||||
}
|
||||
|
||||
public static DropKeyspaceEvent beforeDelete(Object source, String keyspace) {
|
||||
return new DropKeyspaceEvent(source, Type.BEFORE_DELETE, keyspace);
|
||||
}
|
||||
|
||||
public static DeleteEvent beforeDelete(Object source, String keyspace, Serializable id) {
|
||||
return beforeDelete(source, keyspace, id, null);
|
||||
}
|
||||
|
||||
public static DeleteEvent beforeDelete(Object source, String keyspace, Serializable id, Object value) {
|
||||
return new DeleteEvent(source, Type.BEFORE_DELETE, keyspace, id, value);
|
||||
}
|
||||
|
||||
public static DropKeyspaceEvent afterDelete(Object source, String keyspace) {
|
||||
return new DropKeyspaceEvent(source, Type.AFTER_DELETE, keyspace);
|
||||
}
|
||||
|
||||
public static DeleteEvent afterDelete(Object source, String keyspace, Serializable id, Object value) {
|
||||
return new DeleteEvent(source, Type.AFTER_DELETE, keyspace, id, value);
|
||||
}
|
||||
|
||||
public static class InsertEvent extends KeyValueEvent {
|
||||
|
||||
private static final long serialVersionUID = -1;
|
||||
|
||||
InsertEvent(Object source, Type type, String keyspace, Serializable id, Object value) {
|
||||
super(source, type, keyspace, id, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateEvent extends KeyValueEvent {
|
||||
|
||||
private static final long serialVersionUID = -1;
|
||||
|
||||
UpdateEvent(Object source, Type type, String keyspace, Serializable id, Object value) {
|
||||
super(source, type, keyspace, id, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeleteEvent extends KeyValueEvent {
|
||||
|
||||
private static final long serialVersionUID = -1;
|
||||
|
||||
DeleteEvent(Object source, Type type, String keyspace, Serializable id, Object value) {
|
||||
super(source, type, keyspace, id, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DropKeyspaceEvent extends DeleteEvent {
|
||||
|
||||
private static final long serialVersionUID = -1;
|
||||
|
||||
DropKeyspaceEvent(Object source, Type type, String keyspace) {
|
||||
super(source, type, keyspace, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class GetEvent extends KeyValueEvent {
|
||||
|
||||
private static final long serialVersionUID = -1;
|
||||
|
||||
protected GetEvent(Object source, Type type, String keyspace,
|
||||
Serializable id, Object value) {
|
||||
super(source, type, keyspace, id, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -142,6 +142,17 @@ public class MapKeyValueAdapter extends AbstractKeyValueAdapter {
|
||||
getKeySpaceMap(keyspace).clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.keyvalue.core.KeyValueAdapter#hasKeyspace(java.io.Serializable)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasKeyspace(Serializable keyspace) {
|
||||
|
||||
Assert.notNull(keyspace, "Collection must not be null for lookup.");
|
||||
return store.containsKey(keyspace);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.keyvalue.core.KeyValueAdapter#clear()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -37,17 +38,26 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.DeleteEvent;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.DropKeyspaceEvent;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.GetEvent;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.InsertEvent;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.Type;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.UpdateEvent;
|
||||
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class KeyValueTemplateUnitTests {
|
||||
@@ -63,10 +73,12 @@ public class KeyValueTemplateUnitTests {
|
||||
|
||||
private @Mock KeyValueAdapter adapterMock;
|
||||
private KeyValueTemplate template;
|
||||
private @Mock ApplicationContext ctxMock;
|
||||
|
||||
@Before
|
||||
public void setUp() throws InstantiationException, IllegalAccessException {
|
||||
this.template = new KeyValueTemplate(adapterMock);
|
||||
this.template.setApplicationContext(ctxMock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -420,6 +432,225 @@ public class KeyValueTemplateUnitTests {
|
||||
template.setExceptionTranslator(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotPublishEventWhenNoApplicationContextSet() {
|
||||
|
||||
template.setApplicationContext(null);
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.AFTER_DELETE,
|
||||
KeyValueEvent.Type.AFTER_INSERT, KeyValueEvent.Type.AFTER_UPDATE, KeyValueEvent.Type.BEFORE_DELETE,
|
||||
KeyValueEvent.Type.BEFORE_INSERT, KeyValueEvent.Type.BEFORE_UPDATE)));
|
||||
|
||||
template.insert("1", FOO_ONE);
|
||||
|
||||
verifyZeroInteractions(ctxMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotPublishEventWhenNotExplicitlySetForPublication() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.AFTER_DELETE)));
|
||||
|
||||
template.insert("1", FOO_ONE);
|
||||
|
||||
verifyZeroInteractions(ctxMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishBeforeInsertEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.BEFORE_INSERT)));
|
||||
|
||||
template.insert("1", FOO_ONE);
|
||||
|
||||
ArgumentCaptor<InsertEvent> captor = ArgumentCaptor.forClass(InsertEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.BEFORE_INSERT));
|
||||
assertThat(captor.getValue().getId(), is((Serializable) "1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getValue(), is((Object) FOO_ONE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishAfterInsertEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.AFTER_INSERT)));
|
||||
|
||||
template.insert("1", FOO_ONE);
|
||||
|
||||
ArgumentCaptor<InsertEvent> captor = ArgumentCaptor.forClass(InsertEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.AFTER_INSERT));
|
||||
assertThat(captor.getValue().getId(), is((Serializable) "1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getValue(), is((Object) FOO_ONE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishBeforeUpdateEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.BEFORE_UPDATE)));
|
||||
|
||||
template.update("1", FOO_ONE);
|
||||
|
||||
ArgumentCaptor<UpdateEvent> captor = ArgumentCaptor.forClass(UpdateEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.BEFORE_UPDATE));
|
||||
assertThat(captor.getValue().getId(), is((Serializable) "1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getValue(), is((Object) FOO_ONE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishAfterUpdateEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.AFTER_UPDATE)));
|
||||
|
||||
template.update("1", FOO_ONE);
|
||||
|
||||
ArgumentCaptor<UpdateEvent> captor = ArgumentCaptor.forClass(UpdateEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.AFTER_UPDATE));
|
||||
assertThat(captor.getValue().getId(), is((Serializable) "1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getValue(), is((Object) FOO_ONE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishBeforeDeleteEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.BEFORE_DELETE)));
|
||||
|
||||
template.delete("1", FOO_ONE.getClass());
|
||||
|
||||
ArgumentCaptor<DeleteEvent> captor = ArgumentCaptor.forClass(DeleteEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.BEFORE_DELETE));
|
||||
assertThat(captor.getValue().getId(), is((Serializable) "1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getValue(), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishAfterDeleteEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.AFTER_DELETE)));
|
||||
when(adapterMock.delete(eq("1"), eq(FOO_ONE.getClass().getName()))).thenReturn(FOO_ONE);
|
||||
|
||||
template.delete("1", FOO_ONE.getClass());
|
||||
|
||||
ArgumentCaptor<DeleteEvent> captor = ArgumentCaptor.forClass(DeleteEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.AFTER_DELETE));
|
||||
assertThat(captor.getValue().getId(), is((Serializable) "1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getValue(), is((Object) FOO_ONE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishBeforeGetEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.BEFORE_GET)));
|
||||
when(adapterMock.get(eq("1"), eq(FOO_ONE.getClass().getName()))).thenReturn(FOO_ONE);
|
||||
|
||||
template.findById("1", FOO_ONE.getClass());
|
||||
|
||||
ArgumentCaptor<GetEvent> captor = ArgumentCaptor.forClass(GetEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.BEFORE_GET));
|
||||
assertThat(captor.getValue().getId(), is((Serializable) "1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getValue(), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishAfterGetEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.AFTER_GET)));
|
||||
when(adapterMock.get(eq("1"), eq(FOO_ONE.getClass().getName()))).thenReturn(FOO_ONE);
|
||||
|
||||
template.findById("1", FOO_ONE.getClass());
|
||||
|
||||
ArgumentCaptor<GetEvent> captor = ArgumentCaptor.forClass(GetEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.AFTER_GET));
|
||||
assertThat(captor.getValue().getId(), is((Serializable) "1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getValue(), is((Object) FOO_ONE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-91
|
||||
*/
|
||||
@Test
|
||||
public void shouldPublishDropKeyspaceEventCorrectly() {
|
||||
|
||||
template.setEventTypesToPublish(new HashSet<KeyValueEvent.Type>(Arrays.asList(KeyValueEvent.Type.AFTER_DELETE)));
|
||||
|
||||
template.delete(FOO_ONE.getClass());
|
||||
|
||||
ArgumentCaptor<DropKeyspaceEvent> captor = ArgumentCaptor.forClass(DropKeyspaceEvent.class);
|
||||
|
||||
verify(ctxMock, times(1)).publishEvent(captor.capture());
|
||||
verifyNoMoreInteractions(ctxMock);
|
||||
|
||||
assertThat(captor.getValue().getType(), is(Type.AFTER_DELETE));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
|
||||
String foo;
|
||||
|
||||
Reference in New Issue
Block a user