Skip to content

Commit 1bc0426

Browse files
committed
Merge branch 'master' of github.com:SpringSource/spring-data-document
Conflicts: spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java
2 parents 9b97c27 + 057eeb1 commit 1bc0426

File tree

5 files changed

+278
-208
lines changed

5 files changed

+278
-208
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,179 +1,207 @@
1-
package org.springframework.data.persistence.document.mongo;
2-
3-
import java.lang.reflect.Field;
4-
5-
import javax.persistence.Transient;
6-
import javax.persistence.Entity;
7-
import javax.persistence.Id;
8-
9-
import org.apache.commons.logging.Log;
10-
import org.apache.commons.logging.LogFactory;
11-
import org.aspectj.lang.JoinPoint;
12-
import org.aspectj.lang.reflect.FieldSignature;
13-
14-
import org.springframework.dao.InvalidDataAccessResourceUsageException;
15-
import org.springframework.data.document.mongodb.mapping.Document;
16-
17-
import org.springframework.data.persistence.document.DocumentBacked;
18-
import org.springframework.data.persistence.document.DocumentBackedTransactionSynchronization;
19-
import org.springframework.data.persistence.ChangeSet;
20-
import org.springframework.data.persistence.ChangeSetPersister;
21-
import org.springframework.data.persistence.ChangeSetPersister.NotFoundException;
22-
import org.springframework.data.persistence.HashMapChangeSet;
23-
import org.springframework.transaction.support.TransactionSynchronizationManager;
24-
25-
/**
26-
* Aspect to turn an object annotated with @Document into a persistent document
27-
* using Mongo.
28-
*
29-
* @author Thomas Risberg
30-
*/
31-
public aspect MongoDocumentBacking {
32-
33-
private static final Log LOGGER = LogFactory
34-
.getLog(MongoDocumentBacking.class);
35-
36-
// Aspect shared config
37-
private ChangeSetPersister<Object> changeSetPersister;
38-
39-
public void setChangeSetPersister(
40-
ChangeSetPersister<Object> changeSetPersister) {
41-
this.changeSetPersister = changeSetPersister;
42-
}
43-
44-
// ITD to introduce N state to Annotated objects
45-
declare parents : (@Entity *) implements DocumentBacked;
46-
47-
// declare @type: DocumentBacked+: @Configurable;
48-
49-
declare @field: @Document * (@Entity+ *).*:@Transient;
50-
declare @field: ChangeSet (DocumentBacked+).*:@Transient;
51-
declare @field: ChangeSetPersister (DocumentBacked+).*:@Transient;
52-
53-
// -------------------------------------------------------------------------
54-
// Advise user-defined constructors of ChangeSetBacked objects to create a new
55-
// backing ChangeSet
56-
// -------------------------------------------------------------------------
57-
pointcut arbitraryUserConstructorOfChangeSetBackedObject(DocumentBacked entity) :
58-
execution((DocumentBacked+).new(..)) &&
59-
!execution((DocumentBacked+).new(ChangeSet)) &&
60-
this(entity);
61-
62-
pointcut finderConstructorOfChangeSetBackedObject(DocumentBacked entity,
63-
ChangeSet cs) :
64-
execution((DocumentBacked+).new(ChangeSet)) &&
65-
this(entity) &&
66-
args(cs);
67-
68-
protected pointcut entityFieldGet(DocumentBacked entity) :
69-
get(@Document * DocumentBacked+.*) &&
70-
this(entity) &&
71-
!get(* DocumentBacked.*);
72-
73-
protected pointcut entityFieldSet(DocumentBacked entity, Object newVal) :
74-
set(@Document * DocumentBacked+.*) &&
75-
this(entity) &&
76-
args(newVal) &&
77-
!set(* DocumentBacked.*);
78-
79-
// protected pointcut entityIdSet(DocumentBacked entity, Object newVal) :
80-
// set(@Id * DocumentBacked+.*) &&
81-
// this(entity) &&
82-
// args(newVal) &&
83-
// !set(* DocumentBacked.*);
84-
85-
before(DocumentBacked entity) : arbitraryUserConstructorOfChangeSetBackedObject(entity) {
86-
LOGGER
87-
.debug("User-defined constructor called on DocumentBacked object of class "
88-
+ entity.getClass());
89-
entity.itdChangeSetPersister = changeSetPersister;
90-
// Populate all properties
91-
ChangeSet changeSet = new HashMapChangeSet();
92-
// changeSetManager.populateChangeSet(changeSet, entity);
93-
entity.setChangeSet(changeSet);
94-
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
95-
throw new InvalidDataAccessResourceUsageException(
96-
"No transaction synchronization is active");
97-
}
98-
TransactionSynchronizationManager
99-
.registerSynchronization(new DocumentBackedTransactionSynchronization(
100-
changeSetPersister, entity));
101-
}
102-
103-
// -------------------------------------------------------------------------
104-
// ChangeSet-related mixins
105-
// -------------------------------------------------------------------------
106-
// Introduced field
107-
private ChangeSet DocumentBacked.changeSet;
108-
109-
private ChangeSetPersister<?> DocumentBacked.itdChangeSetPersister;
110-
111-
public void DocumentBacked.setChangeSet(ChangeSet cs) {
112-
this.changeSet = cs;
113-
}
114-
115-
public ChangeSet DocumentBacked.getChangeSet() {
116-
return changeSet;
117-
}
118-
119-
// Flush the entity state to the persistent store
120-
public void DocumentBacked.flush() {
121-
Object id = itdChangeSetPersister.getPersistentId(this, this.changeSet);
122-
itdChangeSetPersister.persistState(this, this.changeSet);
123-
}
124-
125-
public Object DocumentBacked.get_persistent_id() {
126-
return itdChangeSetPersister.getPersistentId(this, this.changeSet);
127-
}
128-
129-
/**
130-
* delegates field reads to the state accessors instance
131-
*/
132-
Object around(DocumentBacked entity): entityFieldGet(entity) {
133-
Field f = field(thisJoinPoint);
134-
String propName = f.getName();
135-
LOGGER.trace("GET " + f + " -> ChangeSet value property [" + propName
136-
+ "] using: " + entity.getChangeSet());
137-
if (entity.getChangeSet().getValues().get(propName) == null) {
138-
try {
139-
this.changeSetPersister.getPersistentState(entity.getClass(),
140-
entity.get_persistent_id(), entity.getChangeSet());
141-
} catch (NotFoundException e) {
142-
}
143-
}
144-
Object fValue = entity.getChangeSet().getValues().get(propName);
145-
if (fValue != null) {
146-
return fValue;
147-
}
148-
return proceed(entity);
149-
}
150-
151-
/**
152-
* delegates field writes to the state accessors instance
153-
*/
154-
Object around(DocumentBacked entity, Object newVal) : entityFieldSet(entity, newVal) {
155-
Field f = field(thisJoinPoint);
156-
String propName = f.getName();
157-
LOGGER.trace("SET " + f + " -> ChangeSet number value property [" + propName
158-
+ "] with value=[" + newVal + "]");
159-
entity.getChangeSet().set(propName, newVal);
160-
return proceed(entity, newVal);
161-
}
162-
163-
// /**
164-
// * delegates field writes to the state accessors instance
165-
// */
166-
// Object around(DocumentBacked entity, Object newVal) : entityIdSet(entity, newVal) {
167-
// Field f = field(thisJoinPoint);
168-
// String propName = f.getName();
169-
// LOGGER.trace("SET @Id -> ChangeSet @Id property [" + propName
170-
// + "] with value=[" + newVal + "]");
171-
// entity.getChangeSet().set("_id", newVal);
172-
// return proceed(entity, newVal);
173-
// }
174-
175-
Field field(JoinPoint joinPoint) {
176-
FieldSignature fieldSignature = (FieldSignature) joinPoint.getSignature();
177-
return fieldSignature.getField();
178-
}
179-
}
1+
package org.springframework.data.persistence.document.mongo;
2+
3+
import java.lang.reflect.Field;
4+
5+
import javax.persistence.Transient;
6+
import javax.persistence.Entity;
7+
import javax.persistence.Id;
8+
9+
import org.apache.commons.logging.Log;
10+
import org.apache.commons.logging.LogFactory;
11+
import org.aspectj.lang.JoinPoint;
12+
import org.aspectj.lang.reflect.FieldSignature;
13+
14+
import org.springframework.dao.InvalidDataAccessResourceUsageException;
15+
import org.springframework.data.document.mongodb.mapping.Document;
16+
17+
import org.springframework.data.persistence.document.DocumentBacked;
18+
import org.springframework.data.persistence.document.DocumentBackedTransactionSynchronization;
19+
import org.springframework.data.persistence.ChangeSet;
20+
import org.springframework.data.persistence.ChangeSetPersister;
21+
import org.springframework.data.persistence.ChangeSetPersister.NotFoundException;
22+
import org.springframework.data.persistence.HashMapChangeSet;
23+
import org.springframework.transaction.support.TransactionSynchronizationManager;
24+
25+
/**
26+
* Aspect to turn an object annotated with @Document into a persistent document
27+
* using Mongo.
28+
*
29+
* @author Thomas Risberg
30+
*/
31+
public aspect MongoDocumentBacking {
32+
33+
private static final Log LOGGER = LogFactory
34+
.getLog(MongoDocumentBacking.class);
35+
36+
// Aspect shared config
37+
private ChangeSetPersister<Object> changeSetPersister;
38+
39+
public void setChangeSetPersister(
40+
ChangeSetPersister<Object> changeSetPersister) {
41+
this.changeSetPersister = changeSetPersister;
42+
}
43+
44+
// ITD to introduce N state to Annotated objects
45+
declare parents : (@Entity *) implements DocumentBacked;
46+
47+
// The annotated fields that will be persisted in MongoDB rather than with JPA
48+
declare @field: @Document * (@Entity+ *).*:@Transient;
49+
50+
// -------------------------------------------------------------------------
51+
// Advise user-defined constructors of ChangeSetBacked objects to create a new
52+
// backing ChangeSet
53+
// -------------------------------------------------------------------------
54+
pointcut arbitraryUserConstructorOfChangeSetBackedObject(DocumentBacked entity) :
55+
execution((DocumentBacked+).new(..)) &&
56+
!execution((DocumentBacked+).new(ChangeSet)) &&
57+
this(entity);
58+
59+
pointcut finderConstructorOfChangeSetBackedObject(DocumentBacked entity,
60+
ChangeSet cs) :
61+
execution((DocumentBacked+).new(ChangeSet)) &&
62+
this(entity) &&
63+
args(cs);
64+
65+
protected pointcut entityFieldGet(DocumentBacked entity) :
66+
get(@Document * DocumentBacked+.*) &&
67+
this(entity) &&
68+
!get(* DocumentBacked.*);
69+
70+
protected pointcut entityFieldSet(DocumentBacked entity, Object newVal) :
71+
set(@Document * DocumentBacked+.*) &&
72+
this(entity) &&
73+
args(newVal) &&
74+
!set(* DocumentBacked.*);
75+
76+
// protected pointcut entityIdSet(DocumentBacked entity, Object newVal) :
77+
// set(@Id * DocumentBacked+.*) &&
78+
// this(entity) &&
79+
// args(newVal) &&
80+
// !set(* DocumentBacked.*);
81+
82+
before(DocumentBacked entity) : arbitraryUserConstructorOfChangeSetBackedObject(entity) {
83+
LOGGER
84+
.debug("User-defined constructor called on DocumentBacked object of class "
85+
+ entity.getClass());
86+
// Populate all ITD fields
87+
entity.setChangeSet(new HashMapChangeSet());
88+
entity.itdChangeSetPersister = changeSetPersister;
89+
entity.itdTransactionSynchronization =
90+
new DocumentBackedTransactionSynchronization(changeSetPersister, entity);
91+
registerTransactionSynchronization(entity);
92+
}
93+
94+
private static void registerTransactionSynchronization(DocumentBacked entity) {
95+
if (TransactionSynchronizationManager.isSynchronizationActive()) {
96+
if (!TransactionSynchronizationManager.getSynchronizations().contains(entity.itdTransactionSynchronization)) {
97+
if (LOGGER.isDebugEnabled()) {
98+
LOGGER.debug("Adding transaction synchronization for " + entity.getClass());
99+
}
100+
TransactionSynchronizationManager.registerSynchronization(entity.itdTransactionSynchronization);
101+
}
102+
else {
103+
if (LOGGER.isDebugEnabled()) {
104+
LOGGER.debug("Transaction synchronization already active for " + entity.getClass());
105+
}
106+
}
107+
}
108+
else {
109+
if (LOGGER.isDebugEnabled()) {
110+
LOGGER.debug("Transaction syncronization is not active for " + entity.getClass());
111+
}
112+
}
113+
}
114+
115+
// -------------------------------------------------------------------------
116+
// ChangeSet-related mixins
117+
// -------------------------------------------------------------------------
118+
// Introduced field
119+
@Transient private ChangeSet DocumentBacked.changeSet;
120+
121+
@Transient private ChangeSetPersister<?> DocumentBacked.itdChangeSetPersister;
122+
123+
@Transient private DocumentBackedTransactionSynchronization DocumentBacked.itdTransactionSynchronization;
124+
125+
public void DocumentBacked.setChangeSet(ChangeSet cs) {
126+
this.changeSet = cs;
127+
}
128+
129+
public ChangeSet DocumentBacked.getChangeSet() {
130+
return changeSet;
131+
}
132+
133+
// Flush the entity state to the persistent store
134+
public void DocumentBacked.flush() {
135+
Object id = itdChangeSetPersister.getPersistentId(this, this.changeSet);
136+
itdChangeSetPersister.persistState(this, this.changeSet);
137+
}
138+
139+
public Object DocumentBacked.get_persistent_id() {
140+
return itdChangeSetPersister.getPersistentId(this, this.changeSet);
141+
}
142+
143+
// lifecycle methods
144+
@javax.persistence.PrePersist public void DocumentBacked.prePersist() {
145+
if (LOGGER.isDebugEnabled()) {
146+
LOGGER.debug("JPA lifecycle called PrePersist: " + this.getClass().getName() + " :: " + this.get_persistent_id());
147+
}
148+
registerTransactionSynchronization(this);
149+
}
150+
@javax.persistence.PreUpdate public void DocumentBacked.preUpdate() {
151+
if (LOGGER.isDebugEnabled()) {
152+
LOGGER.debug("JPA lifecycle called PreUpdate: " + this.getClass().getName() + " :: " + this.get_persistent_id());
153+
}
154+
registerTransactionSynchronization(this);
155+
}
156+
@javax.persistence.PreRemove public void DocumentBacked.preRemove() {
157+
if (LOGGER.isDebugEnabled()) {
158+
LOGGER.debug("JPA lifecycle called PreRemove: " + this.getClass().getName() + " :: " + this.get_persistent_id());
159+
}
160+
registerTransactionSynchronization(this);
161+
}
162+
@javax.persistence.PostLoad public void DocumentBacked.postLoad() {
163+
if (LOGGER.isDebugEnabled()) {
164+
LOGGER.debug("JPA lifecycle called PostLoad: " + this.getClass().getName() + " :: " + this.get_persistent_id());
165+
}
166+
registerTransactionSynchronization(this);
167+
}
168+
169+
/**
170+
* delegates field reads to the state accessors instance
171+
*/
172+
Object around(DocumentBacked entity): entityFieldGet(entity) {
173+
Field f = field(thisJoinPoint);
174+
String propName = f.getName();
175+
LOGGER.trace("GET " + f + " -> ChangeSet value property [" + propName
176+
+ "] using: " + entity.getChangeSet());
177+
if (entity.getChangeSet().getValues().get(propName) == null) {
178+
try {
179+
this.changeSetPersister.getPersistentState(entity.getClass(),
180+
entity.get_persistent_id(), entity.getChangeSet());
181+
} catch (NotFoundException e) {
182+
}
183+
}
184+
Object fValue = entity.getChangeSet().getValues().get(propName);
185+
if (fValue != null) {
186+
return fValue;
187+
}
188+
return proceed(entity);
189+
}
190+
191+
/**
192+
* delegates field writes to the state accessors instance
193+
*/
194+
Object around(DocumentBacked entity, Object newVal) : entityFieldSet(entity, newVal) {
195+
Field f = field(thisJoinPoint);
196+
String propName = f.getName();
197+
LOGGER.trace("SET " + f + " -> ChangeSet number value property [" + propName
198+
+ "] with value=[" + newVal + "]");
199+
entity.getChangeSet().set(propName, newVal);
200+
return proceed(entity, newVal);
201+
}
202+
203+
Field field(JoinPoint joinPoint) {
204+
FieldSignature fieldSignature = (FieldSignature) joinPoint.getSignature();
205+
return fieldSignature.getField();
206+
}
207+
}

0 commit comments

Comments
 (0)