From 87bf10a076b47a802c8c4cafba0465d058aaa99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Basl=C3=A9?= Date: Mon, 29 Jun 2015 18:36:10 +0200 Subject: [PATCH] re-add event notifications to template --- .../couchbase/core/CouchbaseTemplate.java | 30 ++++-- .../event/AbstractCouchbaseEventListener.java | 102 ++++++++++++++++++ .../core/mapping/event/AfterDeleteEvent.java | 28 +++++ .../core/mapping/event/AfterSaveEvent.java | 30 ++++++ .../mapping/event/BeforeConvertEvent.java | 28 +++++ .../core/mapping/event/BeforeDeleteEvent.java | 28 +++++ .../core/mapping/event/BeforeSaveEvent.java | 30 ++++++ .../mapping/event/CouchbaseMappingEvent.java | 45 ++++++++ .../mapping/event/LoggingEventListener.java | 59 ++++++++++ .../ValidatingCouchbaseEventListener.java | 67 ++++++++++++ .../AbstractCouchbaseEventListenerTests.java | 58 ++++++++++ .../event/EventContextConfiguration.java | 45 ++++++++ .../event/SimpleMappingEventListener.java | 47 ++++++++ .../couchbase/core/mapping/event/User.java | 52 +++++++++ ...ValidatingCouchbaseEventListenerTests.java | 60 +++++++++++ 15 files changed, 703 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/AbstractCouchbaseEventListener.java create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/AfterDeleteEvent.java create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/AfterSaveEvent.java create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeConvertEvent.java create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeDeleteEvent.java create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeSaveEvent.java create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/CouchbaseMappingEvent.java create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/LoggingEventListener.java create mode 100644 src/main/java/org/springframework/data/couchbase/core/mapping/event/ValidatingCouchbaseEventListener.java create mode 100644 src/test/java/org/springframework/data/couchbase/core/mapping/event/AbstractCouchbaseEventListenerTests.java create mode 100644 src/test/java/org/springframework/data/couchbase/core/mapping/event/EventContextConfiguration.java create mode 100644 src/test/java/org/springframework/data/couchbase/core/mapping/event/SimpleMappingEventListener.java create mode 100644 src/test/java/org/springframework/data/couchbase/core/mapping/event/User.java create mode 100644 src/test/java/org/springframework/data/couchbase/core/mapping/event/ValidatingCouchbaseEventListenerTests.java diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java index ac279d5a..00391477 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java @@ -55,6 +55,12 @@ import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext; import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity; import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty; import org.springframework.data.couchbase.core.mapping.CouchbaseStorable; +import org.springframework.data.couchbase.core.mapping.event.AfterDeleteEvent; +import org.springframework.data.couchbase.core.mapping.event.AfterSaveEvent; +import org.springframework.data.couchbase.core.mapping.event.BeforeConvertEvent; +import org.springframework.data.couchbase.core.mapping.event.BeforeDeleteEvent; +import org.springframework.data.couchbase.core.mapping.event.BeforeSaveEvent; +import org.springframework.data.couchbase.core.mapping.event.CouchbaseMappingEvent; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.BeanWrapper; @@ -179,6 +185,18 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP this.eventPublisher = eventPublisher; } + /** + * Helper method to publish an event if the event publisher is set. + * + * @param event the event to emit. + * @param the enclosed type. + */ + protected void maybeEmitEvent(final CouchbaseMappingEvent event) { + if (eventPublisher != null) { + eventPublisher.publishEvent(event); + } + } + @Override public void save(Object objectToSave) { save(objectToSave, PersistTo.NONE, ReplicateTo.NONE); @@ -363,11 +381,11 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty(); final Long version = versionProperty != null ? beanWrapper.getProperty(versionProperty, Long.class) : null; - //TODO event beforeConvert + maybeEmitEvent(new BeforeConvertEvent(objectToPersist)); final CouchbaseDocument converted = new CouchbaseDocument(); converter.write(objectToPersist, converted); - //TODO event beforeSave + maybeEmitEvent(new BeforeSaveEvent(objectToPersist, converted)); execute(new BucketCallback() { @Override public Boolean doInBucket() throws InterruptedException, ExecutionException { @@ -401,13 +419,13 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP } } }); - //TODO event afterSave + maybeEmitEvent(new AfterSaveEvent(objectToPersist, converted)); } private void doRemove(final Object objectToRemove, final PersistTo persistTo, final ReplicateTo replicateTo) { ensureNotIterable(objectToRemove); - //TODO event BeforeDelete + maybeEmitEvent(new BeforeDeleteEvent(objectToRemove)); if (objectToRemove instanceof String) { execute(new BucketCallback() { @Override @@ -417,7 +435,7 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP return deletedDoc != null; } }); - //TODO event afterDelete + maybeEmitEvent(new AfterDeleteEvent(objectToRemove)); return; } @@ -432,7 +450,7 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP return deletedDoc != null; } }); - //TODO event afterDelete + maybeEmitEvent(new AfterDeleteEvent(objectToRemove)); } private T mapToEntity(String id, Document data, Class entityClass) { diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/AbstractCouchbaseEventListener.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/AbstractCouchbaseEventListener.java new file mode 100644 index 00000000..376718e1 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/AbstractCouchbaseEventListener.java @@ -0,0 +1,102 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.context.ApplicationListener; +import org.springframework.core.GenericTypeResolver; +import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; + +/** + * Base class to implement domain class specific {@link ApplicationListener}s. + * + * @author Jon Brisbin + * @author Oliver Gierke + * @author Martin Baumgartner + * @author Michael Nitschinger + */ +public class AbstractCouchbaseEventListener implements ApplicationListener> { + private static final Logger LOG = LoggerFactory.getLogger(AbstractCouchbaseEventListener.class); + private final Class domainClass; + + public AbstractCouchbaseEventListener() { + Class typeArgument = GenericTypeResolver.resolveTypeArgument(getClass(), AbstractCouchbaseEventListener.class); + domainClass = typeArgument == null ? Object.class : typeArgument; + } + + @SuppressWarnings("rawtypes") + public void onApplicationEvent(CouchbaseMappingEvent event) { + + E source = (E) event.getSource(); + // Check for matching domain type and invoke callbacks + if (source != null && !domainClass.isAssignableFrom(source.getClass())) { + return; + } + + if (event instanceof BeforeDeleteEvent) { + onBeforeDelete(event.getSource(), event.getDocument()); + return; + } + else if (event instanceof AfterDeleteEvent) { + onAfterDelete(event.getSource(), event.getDocument()); + return; + } + + if (event instanceof BeforeConvertEvent) { + onBeforeConvert(source); + } + else if (event instanceof BeforeSaveEvent) { + onBeforeSave(source, event.getDocument()); + } + else if (event instanceof AfterSaveEvent) { + onAfterSave(source, event.getDocument()); + } + } + + public void onBeforeConvert(E source) { + if (LOG.isDebugEnabled()) { + LOG.debug("onBeforeConvert({})", source); + } + } + + public void onBeforeSave(E source, CouchbaseDocument doc) { + if (LOG.isDebugEnabled()) { + LOG.debug("onBeforeSave({}, {})", source, doc); + } + } + + public void onAfterSave(E source, CouchbaseDocument doc) { + if (LOG.isDebugEnabled()) { + LOG.debug("onAfterSave({}, {})", source, doc); + } + } + + public void onAfterDelete(Object source, CouchbaseDocument doc) { + if (LOG.isDebugEnabled()) { + LOG.debug("onAfterConvert({})", doc); + } + } + + public void onBeforeDelete(Object source, CouchbaseDocument doc) { + if (LOG.isDebugEnabled()) { + LOG.debug("onAfterConvert({})", doc); + } + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/AfterDeleteEvent.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/AfterDeleteEvent.java new file mode 100644 index 00000000..d129dbb2 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/AfterDeleteEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +/** + * @author Michael Nitschinger + */ +public class AfterDeleteEvent extends CouchbaseMappingEvent { + + public AfterDeleteEvent(E source) { + super(source, null); + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/AfterSaveEvent.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/AfterSaveEvent.java new file mode 100644 index 00000000..ac0df8ae --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/AfterSaveEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; + +/** + * @author Michael Nitschinger + */ +public class AfterSaveEvent extends CouchbaseMappingEvent { + + public AfterSaveEvent(E source, CouchbaseDocument document) { + super(source, document); + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeConvertEvent.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeConvertEvent.java new file mode 100644 index 00000000..36b2ec08 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeConvertEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +/** + * @author Michael Nitschinger + */ +public class BeforeConvertEvent extends CouchbaseMappingEvent { + + public BeforeConvertEvent(E source) { + super(source, null); + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeDeleteEvent.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeDeleteEvent.java new file mode 100644 index 00000000..91ccf27f --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeDeleteEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +/** + * @author Michael Nitschinger + */ +public class BeforeDeleteEvent extends CouchbaseMappingEvent { + + public BeforeDeleteEvent(E source) { + super(source, null); + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeSaveEvent.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeSaveEvent.java new file mode 100644 index 00000000..b63b830f --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/BeforeSaveEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; + +/** + * @author Michael Nitschinger + */ +public class BeforeSaveEvent extends CouchbaseMappingEvent { + + public BeforeSaveEvent(E source, CouchbaseDocument document) { + super(source, document); + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/CouchbaseMappingEvent.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/CouchbaseMappingEvent.java new file mode 100644 index 00000000..3ab315db --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/CouchbaseMappingEvent.java @@ -0,0 +1,45 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +import org.springframework.context.ApplicationEvent; +import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; + +/** + * A mapping event. + * + * @author Michael Nitschinger + */ +public class CouchbaseMappingEvent extends ApplicationEvent { + + private final CouchbaseDocument document; + + public CouchbaseMappingEvent(T source, CouchbaseDocument document) { + super(source); + this.document = document; + } + + public CouchbaseDocument getDocument() { + return document; + } + + @SuppressWarnings("unchecked") + @Override + public T getSource() { + return (T) super.getSource(); + } +} diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/LoggingEventListener.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/LoggingEventListener.java new file mode 100644 index 00000000..edf0dbdf --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/LoggingEventListener.java @@ -0,0 +1,59 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.context.ApplicationListener; +import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; + +/** + * A{@link ApplicationListener} for Couchbase mapping events logging the events. + * + * @author Michael Nitschinger + */ +public class LoggingEventListener extends AbstractCouchbaseEventListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(LoggingEventListener.class); + + @Override + public void onBeforeDelete(Object source, CouchbaseDocument doc) { + LOGGER.info("onBeforeDelete: {}, {}", source, doc); + } + + @Override + public void onAfterDelete(Object source, CouchbaseDocument doc) { + LOGGER.info("onAfterDelete: {} {}", source, doc); + } + + @Override + public void onAfterSave(Object source, CouchbaseDocument doc) { + LOGGER.info("onAfterSave: {}, {}", source, doc); + } + + @Override + public void onBeforeSave(Object source, CouchbaseDocument doc) { + LOGGER.info("onBeforeSave: {}, {}", source, doc); + } + + @Override + public void onBeforeConvert(Object source) { + LOGGER.info("onBeforeConvert: {}, {}", source); + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/event/ValidatingCouchbaseEventListener.java b/src/main/java/org/springframework/data/couchbase/core/mapping/event/ValidatingCouchbaseEventListener.java new file mode 100644 index 00000000..18468288 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/event/ValidatingCouchbaseEventListener.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012-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.couchbase.core.mapping.event; + +import java.util.Set; + +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; +import org.springframework.util.Assert; + +/** + * javax.validation dependant entities validator. When it is registered as Spring component its automatically invoked + * before entities are saved in database. + * + * @author Maciej Walkowiak + * @author Michael Nitschinger + */ +public class ValidatingCouchbaseEventListener extends AbstractCouchbaseEventListener { + + private static final Logger LOG = LoggerFactory.getLogger(ValidatingCouchbaseEventListener.class); + + private final Validator validator; + + /** + * Creates a new {@link ValidatingCouchbaseEventListener} using the given {@link Validator}. + * + * @param validator must not be {@literal null}. + */ + public ValidatingCouchbaseEventListener(Validator validator) { + Assert.notNull(validator); + this.validator = validator; + } + + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public void onBeforeSave(Object source, CouchbaseDocument dbo) { + + LOG.debug("Validating object: {}", source); + Set violations = validator.validate(source); + + if (!violations.isEmpty()) { + + LOG.info("During object: {} validation violations found: {}", source, violations); + throw new ConstraintViolationException(violations); + } + } + +} diff --git a/src/test/java/org/springframework/data/couchbase/core/mapping/event/AbstractCouchbaseEventListenerTests.java b/src/test/java/org/springframework/data/couchbase/core/mapping/event/AbstractCouchbaseEventListenerTests.java new file mode 100644 index 00000000..4c3af0e6 --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/core/mapping/event/AbstractCouchbaseEventListenerTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013 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.couchbase.core.mapping.event; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.couchbase.core.CouchbaseTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +/** + * @author Michael Nitschinger + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = EventContextConfiguration.class) +@TestExecutionListeners({DependencyInjectionTestExecutionListener.class}) +public class AbstractCouchbaseEventListenerTests { + + @Autowired + private CouchbaseTemplate couchbaseTemplate; + + @Autowired + private SimpleMappingEventListener eventListener; + + @Test + public void shouldEmitEvents() { + int beforeSave = eventListener.onBeforeSaveEvents.size(); + int afterSave = eventListener.onAfterSaveEvents.size(); + int beforeConvert = eventListener.onBeforeConvertEvents.size(); + + couchbaseTemplate.save(new User("john smith", 18)); + + assertEquals(beforeSave + 1, eventListener.onBeforeSaveEvents.size()); + assertEquals(afterSave + 1, eventListener.onAfterSaveEvents.size()); + assertEquals(beforeConvert + 1, eventListener.onBeforeConvertEvents.size()); + } + +} diff --git a/src/test/java/org/springframework/data/couchbase/core/mapping/event/EventContextConfiguration.java b/src/test/java/org/springframework/data/couchbase/core/mapping/event/EventContextConfiguration.java new file mode 100644 index 00000000..34cf0fed --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/core/mapping/event/EventContextConfiguration.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013 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.couchbase.core.mapping.event; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.couchbase.UnitTestApplicationConfig; +import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; + +/** + * @author Michael Nitschinger + */ +@Configuration +public class EventContextConfiguration extends UnitTestApplicationConfig { + + @Bean + public LocalValidatorFactoryBean validator() { + return new LocalValidatorFactoryBean(); + } + + @Bean + public ValidatingCouchbaseEventListener validatingCouchbaseEventListener() { + return new ValidatingCouchbaseEventListener(validator()); + } + + @Bean + public SimpleMappingEventListener simpleMappingEventListener() { + return new SimpleMappingEventListener(); + } + +} diff --git a/src/test/java/org/springframework/data/couchbase/core/mapping/event/SimpleMappingEventListener.java b/src/test/java/org/springframework/data/couchbase/core/mapping/event/SimpleMappingEventListener.java new file mode 100644 index 00000000..ac216bcc --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/core/mapping/event/SimpleMappingEventListener.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 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.couchbase.core.mapping.event; + +import java.util.ArrayList; + +import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; + +/** + * @author Michael Nitschinger + */ +public class SimpleMappingEventListener extends AbstractCouchbaseEventListener { + + public final ArrayList> onBeforeConvertEvents = new ArrayList>(); + public final ArrayList> onBeforeSaveEvents = new ArrayList>(); + public final ArrayList> onAfterSaveEvents = new ArrayList>(); + + @Override + public void onBeforeConvert(Object source) { + onBeforeConvertEvents.add(new BeforeConvertEvent(source)); + } + + @Override + public void onBeforeSave(Object source, CouchbaseDocument doc) { + onBeforeSaveEvents.add(new BeforeSaveEvent(source, doc)); + } + + @Override + public void onAfterSave(Object source, CouchbaseDocument doc) { + onAfterSaveEvents.add(new AfterSaveEvent(source, doc)); + } + +} diff --git a/src/test/java/org/springframework/data/couchbase/core/mapping/event/User.java b/src/test/java/org/springframework/data/couchbase/core/mapping/event/User.java new file mode 100644 index 00000000..f6aa81e0 --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/core/mapping/event/User.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013 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.couchbase.core.mapping.event; + +import javax.validation.constraints.Min; +import javax.validation.constraints.Size; + +import org.springframework.data.annotation.Id; + +/** + * @author Michael Nitschinger + */ +public class User { + + @Id + private String id; + + @Size(min = 10) + private String name; + + @Min(18) + private Integer age; + + public User(String name, Integer age) { + id = "id"; + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public Integer getAge() { + return age; + } + +} diff --git a/src/test/java/org/springframework/data/couchbase/core/mapping/event/ValidatingCouchbaseEventListenerTests.java b/src/test/java/org/springframework/data/couchbase/core/mapping/event/ValidatingCouchbaseEventListenerTests.java new file mode 100644 index 00000000..ffd4137e --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/core/mapping/event/ValidatingCouchbaseEventListenerTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013 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.couchbase.core.mapping.event; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import javax.validation.ConstraintViolationException; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.couchbase.core.CouchbaseTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Michael Nitschinger + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = EventContextConfiguration.class) +public class ValidatingCouchbaseEventListenerTests { + + @Autowired + CouchbaseTemplate template; + + @Test + public void shouldThrowConstraintViolationException() { + User user = new User("john", 17); + + try { + template.save(user); + fail(); + } + catch (ConstraintViolationException e) { + assertThat(e.getConstraintViolations().size(), equalTo(2)); + } + } + + @Test + public void shouldNotThrowAnyExceptions() { + template.save(new User("john smith", 18)); + } +}