Permalink
Browse files

DATAMONGO-577 - Added support for auditing.

Introduced AuditingEventListener to invoke auditing subsystem available through Spring Data Commons. Added <mongo:auditing /> namespace element to transparently activate it.
  • Loading branch information...
1 parent 772a140 commit 94823500624432de101e464f6adf72d98b37a347 @olivergierke olivergierke committed Nov 21, 2012
Showing with 849 additions and 94 deletions.
  1. +14 −0 ...ata-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java
  2. +2 −0 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java
  3. +19 −2 ...ta-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java
  4. +79 −0 ...godb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java
  5. +6 −6 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java
  6. +0 −40 ...ngodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java
  7. +0 −8 ...odb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java
  8. +0 −16 ...ta-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java
  9. +0 −7 ...-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java
  10. +3 −0 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Version.java
  11. +53 −0 ...godb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java
  12. +7 −5 ...mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java
  13. +7 −1 .../main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java
  14. +3 −2 spring-data-mongodb/src/main/resources/META-INF/spring.schemas
  15. +483 −0 spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd
  16. +68 −0 ...-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java
  17. +89 −0 ...test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java
  18. +12 −0 spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/auditing.xml
  19. +1 −4 .../test/resources/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests-context.xml
  20. +3 −3 ...ces/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml
@@ -27,12 +27,15 @@
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.authentication.UserCredentials;
+import org.springframework.data.mapping.model.MappingContextIsNewStrategyFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
+import org.springframework.data.support.CachingIsNewStrategyFactory;
+import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -137,6 +140,17 @@ public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
}
/**
+ * Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
+ *
+ * @return
+ * @throws ClassNotFoundException
+ */
+ @Bean
+ public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
+ return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(mongoMappingContext()));
+ }
+
+ /**
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
* {@link #mongoMappingContext()}. Returns an empty {@link CustomConversions} instance by default.
@@ -26,4 +26,6 @@
static final String MONGO = "mongo";
static final String DB_FACTORY = "mongoDbFactory";
static final String VALIDATING_EVENT_LISTENER = "validatingMongoEventListener";
+ static final String IS_NEW_STRATEGY_FACTORY = "isNewStrategyFactory";
+
}
@@ -49,6 +49,8 @@
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.config.BeanComponentDefinitionBuilder;
+import org.springframework.data.config.ParsingUtils;
+import org.springframework.data.mapping.model.MappingContextIsNewStrategyFactory;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
@@ -88,6 +90,8 @@ protected AbstractBeanDefinition parseInternal(Element element, ParserContext pa
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition);
+ createIsNewStrategyFactoryBeanDefinition(ctxRef, parserContext, element);
+
// Need a reference to a Mongo instance
String dbFactoryRef = element.getAttribute("db-factory-ref");
if (!StringUtils.hasText(dbFactoryRef)) {
@@ -163,7 +167,7 @@ private RuntimeBeanReference getValidator(Object source, ParserContext parserCon
return new RuntimeBeanReference(validatorName);
}
- private String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
+ static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
BeanDefinition conversionsDefinition) {
String ctxRef = element.getAttribute("mapping-context-ref");
@@ -241,7 +245,7 @@ private BeanDefinition getCustomConversions(Element element, ParserContext parse
return null;
}
- public Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
+ private static Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
String basePackage = element.getAttribute(BASE_PACKAGE);
@@ -280,6 +284,19 @@ public BeanMetadataElement parseConverter(Element element, ParserContext parserC
return null;
}
+ public static String createIsNewStrategyFactoryBeanDefinition(String mappingContextRef, ParserContext context,
+ Element element) {
+
+ BeanDefinitionBuilder mappingContextStrategyFactoryBuilder = BeanDefinitionBuilder
+ .rootBeanDefinition(MappingContextIsNewStrategyFactory.class);
+ mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
+
+ context.getRegistry().registerBeanDefinition(IS_NEW_STRATEGY_FACTORY,
+ ParsingUtils.getSourceBeanDefinition(mappingContextStrategyFactoryBuilder, context, element));
+
+ return IS_NEW_STRATEGY_FACTORY;
+ }
+
/**
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
*
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 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.mongodb.config;
+
+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.IsNewAwareAuditingHandlerBeanDefinitionParser;
+import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener;
+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 MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+ /*
+ * (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.AbstractBeanDefinitionParser#shouldGenerateId()
+ */
+ @Override
+ protected boolean shouldGenerateId() {
+ return true;
+ }
+
+ /*
+ * (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 builder) {
+
+ BeanDefinitionRegistry registry = parserContext.getRegistry();
+
+ if (!registry.containsBeanDefinition(BeanNames.IS_NEW_STRATEGY_FACTORY)) {
+
+ String mappingContextName = BeanNames.MAPPING_CONTEXT;
+
+ if (!registry.containsBeanDefinition(BeanNames.MAPPING_CONTEXT)) {
+ mappingContextName = MappingMongoConverterParser.potentiallyCreateMappingContext(element, parserContext, null);
+ }
+
+ MappingMongoConverterParser.createIsNewStrategyFactoryBeanDefinition(mappingContextName, parserContext, element);
+ }
+
+ BeanDefinitionParser parser = new IsNewAwareAuditingHandlerBeanDefinitionParser(BeanNames.IS_NEW_STRATEGY_FACTORY);
+ BeanDefinition handlerBeanDefinition = parser.parse(element, parserContext);
+
+ builder.addConstructorArgValue(handlerBeanDefinition);
+ }
+}
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 the original author or authors.
+ * Copyright 2011-2012 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.
@@ -21,17 +21,16 @@
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
/**
- * {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB based repositories.
+ * {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB configuration.
*
* @author Oliver Gierke
*/
public class MongoNamespaceHandler extends NamespaceHandlerSupport {
/*
- * (non-Javadoc)
- *
- * @see org.springframework.beans.factory.xml.NamespaceHandler#init()
- */
+ * (non-Javadoc)
+ * @see org.springframework.beans.factory.xml.NamespaceHandler#init()
+ */
public void init() {
RepositoryConfigurationExtension extension = new MongoRepositoryConfigurationExtension();
@@ -42,5 +41,6 @@ public void init() {
registerBeanDefinitionParser("mongo", new MongoParser());
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
registerBeanDefinitionParser("jmx", new MongoJmxParser());
+ registerBeanDefinitionParser("auditing", new MongoAuditingBeanDefinitionParser());
}
}
@@ -23,7 +23,6 @@
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.mapping.model.BasicPersistentEntity;
-import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.MongoCollectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
@@ -38,7 +37,6 @@
*
* @author Jon Brisbin
* @author Oliver Gierke
- * @author Patryk Wasik
*/
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
MongoPersistentEntity<T>, ApplicationContextAware {
@@ -73,27 +71,6 @@ public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {
}
}
- /*
- * (non-Javadoc)
- * @see org.springframework.data.mapping.MutablePersistentEntity#addPersistentProperty(P)
- */
- @Override
- public void addPersistentProperty(MongoPersistentProperty property) {
-
- if (property.isVersionProperty()) {
-
- if (this.versionProperty != null) {
- throw new MappingException(String.format(
- "Attempt to add version property %s but already have property %s registered "
- + "as version. Check your mapping configuration!", property.getField(), versionProperty.getField()));
- }
-
- this.versionProperty = property;
- }
-
- super.addPersistentProperty(property);
- }
-
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
@@ -110,27 +87,10 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getCollection()
*/
public String getCollection() {
-
Expression expression = parser.parseExpression(collection, ParserContext.TEMPLATE_EXPRESSION);
return expression.getValue(context, String.class);
}
- /*
- * (non-Javadoc)
- * @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getVersionProperty()
- */
- public MongoPersistentProperty getVersionProperty() {
- return versionProperty;
- }
-
- /*
- * (non-Javadoc)
- * @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#hasVersionProperty()
- */
- public boolean hasVersionProperty() {
- return getVersionProperty() != null;
- }
-
/**
* {@link Comparator} implementation inspecting the {@link MongoPersistentProperty}'s order.
*
@@ -153,14 +153,6 @@ public DBRef getDBRef() {
return getField().getAnnotation(DBRef.class);
}
- /*
- * (non-Javadoc)
- * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isVersionProperty()
- */
- public boolean isVersionProperty() {
- return getField().isAnnotationPresent(Version.class);
- }
-
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
@@ -21,7 +21,6 @@
* MongoDB specific {@link PersistentEntity} abstraction.
*
* @author Oliver Gierke
- * @author Patryk Wasik
*/
public interface MongoPersistentEntity<T> extends PersistentEntity<T, MongoPersistentProperty> {
@@ -31,19 +30,4 @@
* @return
*/
String getCollection();
-
- /**
- * Returns the {@link MongoPersistentProperty} that represents the version attribute of an entity. Will not be
- * {@literal null} if {@link #hasVersionProperty()}.
- *
- * @return
- */
- MongoPersistentProperty getVersionProperty();
-
- /**
- * Returns whether the entity has a property representing the version of the entity.
- *
- * @return
- */
- boolean hasVersionProperty();
}
@@ -57,13 +57,6 @@
DBRef getDBRef();
/**
- * Returns whether the property is representing the version attribute of an entity.
- *
- * @return
- */
- boolean isVersionProperty();
-
- /**
* Simple {@link Converter} implementation to transform a {@link MongoPersistentProperty} into its field name.
*
* @author Oliver Gierke
@@ -27,10 +27,13 @@
*
* @since 1.4
* @author Patryk Wasik
+ * @deprecated use {@link org.springframework.data.annotation.Version} instead.
*/
+@Deprecated
@Documented
@Target({ FIELD })
@Retention(RUNTIME)
+@org.springframework.data.annotation.Version
public @interface Version {
}
Oops, something went wrong.

0 comments on commit 9482350

Please sign in to comment.