DATAJPA-501 - Adapted auditing configuration to latest changes in Spring Data Commons.

The configuration subsystem now sets up an AuditingHandler with a direct reference to a MappingContext. We now also wire an ObjectFactory into the AuditingEntityListener instead of the AuditingHandler directly.

This also lets us get rid off the need to mark AuditorAware instances as lazy initialized as the initialization chain is interrupted right at the AuditingEntityListener.

Related issues: DATACMNS-365.
This commit is contained in:
Oliver Gierke
2014-03-18 20:06:47 +01:00
parent e2e692ce83
commit 467903b96c
13 changed files with 183 additions and 33 deletions

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2014 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.jpa.domain.sample;
import java.util.Date;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
/**
* @author Oliver Gierke
* @since 1.6
*/
@MappedSuperclass
public class AbstractAnnotatedAuditable {
private @Id @GeneratedValue Long id;
private @CreatedBy @ManyToOne AuditableUser createdBy;
private @CreatedDate @Temporal(TemporalType.TIMESTAMP) Date createAt;
private @ManyToOne AuditableUser lastModifiedBy;
private @Temporal(TemporalType.TIMESTAMP) Date lastModifiedAt;
public Long getId() {
return id;
}
public AuditableUser getCreatedBy() {
return createdBy;
}
public Date getCreateAt() {
return createAt;
}
@LastModifiedBy
public AuditableUser getLastModifiedBy() {
return lastModifiedBy;
}
@LastModifiedDate
public Date getLastModifiedAt() {
return lastModifiedAt;
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2014 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.jpa.domain.sample;
import javax.persistence.Entity;
/**
* @author Oliver Gierke
* @since 1.6
*/
@Entity
public class AnnotatedAuditableUser extends AbstractAnnotatedAuditable {
}

View File

@@ -23,9 +23,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Auditable;
import org.springframework.data.jpa.domain.sample.AnnotatedAuditableUser;
import org.springframework.data.jpa.domain.sample.AuditableRole;
import org.springframework.data.jpa.domain.sample.AuditableUser;
import org.springframework.data.jpa.domain.sample.AuditorAwareStub;
import org.springframework.data.jpa.repository.sample.AnnotatedAuditableUserRepository;
import org.springframework.data.jpa.repository.sample.AuditableUserRepository;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
@@ -43,11 +45,10 @@ import org.springframework.transaction.annotation.Transactional;
@DirtiesContext
public class AuditingEntityListenerTests {
@Autowired
AuditableUserRepository repository;
@Autowired AuditableUserRepository repository;
@Autowired AnnotatedAuditableUserRepository annotatedUserRepository;
@Autowired
AuditorAwareStub auditorAware;
@Autowired AuditorAwareStub auditorAware;
AuditableUser user;
@@ -97,6 +98,18 @@ public class AuditingEntityListenerTests {
assertUserIsAuditor(user, role);
}
/**
* @see DATAJPA-501
*/
@Test
public void usesAnnotationMetadata() {
AnnotatedAuditableUser auditableUser = annotatedUserRepository.save(new AnnotatedAuditableUser());
assertThat(auditableUser.getCreateAt(), is(notNullValue()));
assertThat(auditableUser.getLastModifiedBy(), is(notNullValue()));
}
private static void assertDatesSet(Auditable<?, ?> auditable) {
assertThat(auditable.getCreatedDate(), is(notNullValue()));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2008-2013 the original author or authors.
* Copyright 2008-2014 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.
@@ -39,13 +39,11 @@ public class AuditingBeanDefinitionParserTests {
@Test
public void settingDatesIsConfigured() {
assertSetDatesIsSetTo("auditing/auditing-namespace-context.xml", "true");
}
@Test
public void notSettingDatesIsConfigured() {
assertSetDatesIsSetTo("auditing/auditing-namespace-context2.xml", "false");
}
@@ -55,15 +53,14 @@ public class AuditingBeanDefinitionParserTests {
@Test
public void wiresDateTimeProviderIfConfigured() {
String location = "auditing/auditing-namespace-context3.xml";
BeanDefinition definition = getBeanDefinition(location);
BeanDefinition definition = getBeanDefinition("auditing/auditing-namespace-context3.xml");
PropertyValue value = definition.getPropertyValues().getPropertyValue("dateTimeProvider");
assertThat(value, is(notNullValue()));
assertThat(value.getValue(), is(instanceOf(RuntimeBeanReference.class)));
assertThat(((RuntimeBeanReference) value.getValue()).getBeanName(), is("dateTimeProvider"));
BeanFactory factory = loadFactoryFrom(location);
BeanFactory factory = loadFactoryFrom("auditing/auditing-namespace-context3.xml");
Object bean = factory.getBean(AuditingBeanDefinitionParser.AUDITING_ENTITY_LISTENER_CLASS_NAME);
assertThat(bean, is(notNullValue()));
}
@@ -90,9 +87,14 @@ public class AuditingBeanDefinitionParserTests {
private BeanDefinition getBeanDefinition(String configFile) {
DefaultListableBeanFactory factory = loadFactoryFrom(configFile);
BeanDefinition definition = factory
.getBeanDefinition(AuditingBeanDefinitionParser.AUDITING_ENTITY_LISTENER_CLASS_NAME);
return (BeanDefinition) definition.getPropertyValues().getPropertyValue("auditingHandler").getValue();
BeanDefinition handlerDefinition = (BeanDefinition) definition.getPropertyValues()
.getPropertyValue("auditingHandler").getValue();
String beanName = handlerDefinition.getPropertyValues().getPropertyValue("targetBeanName").getValue().toString();
return factory.getBeanDefinition(beanName);
}
private DefaultListableBeanFactory loadFactoryFrom(String configFile) {

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2014 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.jpa.repository.sample;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.jpa.domain.sample.AnnotatedAuditableUser;
import org.springframework.data.repository.CrudRepository;
/**
* Repository interface for {@code AuditableUser}.
*
* @author Oliver Gierke
*/
@Lazy
public interface AnnotatedAuditableUserRepository extends CrudRepository<AnnotatedAuditableUser, Long> {
}