entityClass, Field f) throws DataAccessException;
+
+}
diff --git a/spring-data-commons-aspects/src/main/java/org/springframework/persistence/GeneratedFieldForeignStoreKeyManager.java b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/GeneratedFieldForeignStoreKeyManager.java
new file mode 100644
index 000000000..8a8209bb2
--- /dev/null
+++ b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/GeneratedFieldForeignStoreKeyManager.java
@@ -0,0 +1,65 @@
+package org.springframework.persistence;
+
+import java.lang.reflect.Field;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.dao.DataAccessException;
+
+/**
+ * Stores keys in generated additional persistent fields
+ * that Roo will add. e.g.
+ *
+ *
+ * atForeignStore
+ * Person Person;
+ *
+ * long person_id;
+ *
+ *
+ * @author
+ *
+ */
+public class GeneratedFieldForeignStoreKeyManager extends
+ OrderedForeignStoreKeyManager {
+
+ private final Log log = LogFactory.getLog(getClass());
+
+
+ @Override
+ public Object findForeignStoreKey(Roo_GeneratedForeignStoreKeys entity, Field foreignStore, Class requiredClass)
+ throws DataAccessException {
+ String methodName = "get" + propertyName(foreignStore);
+ Object key = RooConventionEntityOperations.invokeNoArgMethod(entity.getClass(), methodName, entity);
+ log.info("FIND foreign store property " + foreignStore + " <- Entity generated String property [" + methodName + "] returned [" + key + "]");
+ return key;
+ }
+
+ @Override
+ public void storeForeignStoreKey(Roo_GeneratedForeignStoreKeys entity, Field foreignStore,
+ Object key) throws DataAccessException {
+ String methodName = "set" + propertyName(foreignStore);
+ RooConventionEntityOperations.invoke(entity.getClass(), methodName, entity, new Class>[] { key.getClass()}, key);
+ log.info("STORE foreign store property " + foreignStore + " -> Entity generated String property [" + methodName + "] with key value [" + key + "]");
+ }
+
+ @Override
+ public void clearForeignStoreKey(Roo_GeneratedForeignStoreKeys entity, Field foreignStore, Class keyClass) throws DataAccessException {
+ String methodName = "set" + propertyName(foreignStore);
+ RooConventionEntityOperations.invoke(entity.getClass(), methodName, entity, new Class>[] { keyClass }, null);
+ log.info("CKEAR foreign store property " + foreignStore + " -> Entity generated String property [" + methodName + "]");
+ }
+
+
+ @Override
+ public boolean isSupportedField(Class clazz, Field f) {
+ // Check for marker interface
+ return Roo_GeneratedForeignStoreKeys.class.isAssignableFrom(clazz);
+ }
+
+
+ private String propertyName(Field f) {
+ return "_" + f.getName() + "_Id";
+ }
+
+}
diff --git a/spring-data-commons-aspects/src/main/java/org/springframework/persistence/InvalidFieldAnnotationException.java b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/InvalidFieldAnnotationException.java
new file mode 100644
index 000000000..3741b96c2
--- /dev/null
+++ b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/InvalidFieldAnnotationException.java
@@ -0,0 +1,20 @@
+package org.springframework.persistence;
+
+import java.lang.reflect.Field;
+
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+
+/**
+ * Exception thrown on an attempt to use a field with an invalid
+ * RelatedEntity annotation.
+ *
+ * @author Rod Johnson
+ */
+public class InvalidFieldAnnotationException extends
+ InvalidDataAccessApiUsageException {
+
+ public InvalidFieldAnnotationException(Class> entityClass, Field f, String reason) {
+ super("Field [" + f.getName() + "] has invalid RelatedEntity annotation: reason='" + reason + "'", null);
+ }
+
+}
diff --git a/spring-data-commons-aspects/src/main/java/org/springframework/persistence/JpaEntityForeignStoreFieldTransience.aj b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/JpaEntityForeignStoreFieldTransience.aj
new file mode 100644
index 000000000..05b6f47d2
--- /dev/null
+++ b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/JpaEntityForeignStoreFieldTransience.aj
@@ -0,0 +1,17 @@
+package org.springframework.persistence;
+
+import javax.persistence.Transient;
+import javax.persistence.Entity;
+
+/**
+ * Aspect to annotate @ForeignStore fields as JPA @Transient to stop
+ * JPA trying to manage them itself
+ * @author Rod Johnson
+ *
+ */
+public privileged aspect JpaEntityForeignStoreFieldTransience {
+
+ declare @field : @RelatedEntity * (@Entity *).* : @Transient;
+
+
+}
diff --git a/spring-data-commons-aspects/src/main/java/org/springframework/persistence/MappingValidator.java b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/MappingValidator.java
new file mode 100644
index 000000000..8143d0543
--- /dev/null
+++ b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/MappingValidator.java
@@ -0,0 +1,20 @@
+package org.springframework.persistence;
+
+import java.lang.reflect.Field;
+
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+
+/**
+ * Interface to validate RelatedAnnotation annotation usage
+ * and other mapping constructs.
+ *
+ * @author Rod Johnson
+ *
+ */
+public interface MappingValidator {
+
+ void validateGet(Class> entityClass, Field f, RelatedEntity re) throws InvalidDataAccessApiUsageException;
+
+ void validateSetTo(Class> entityClass, Field f, RelatedEntity re, Object newVal) throws InvalidDataAccessApiUsageException, IllegalArgumentException;
+
+}
diff --git a/spring-data-commons-aspects/src/main/java/org/springframework/persistence/OrderedForeignStoreKeyManager.java b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/OrderedForeignStoreKeyManager.java
new file mode 100644
index 000000000..c4211a01a
--- /dev/null
+++ b/spring-data-commons-aspects/src/main/java/org/springframework/persistence/OrderedForeignStoreKeyManager.java
@@ -0,0 +1,45 @@
+package org.springframework.persistence;
+
+import java.lang.reflect.Field;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.core.Ordered;
+import org.springframework.dao.DataAccessException;
+
+/**
+ * Convenient base class for ForeignStoreKeyManager implementations that adds
+ * ordering support.
+ *
+ * @author Rod Johnson
+ */
+public abstract class OrderedForeignStoreKeyManager implements ForeignStoreKeyManager, Ordered {
+
+ protected final Log log = LogFactory.getLog(getClass());
+
+ private int order = Integer.MAX_VALUE;
+
+ @Override
+ public int getOrder() {
+ return this.order;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ /**
+ * Subclasses can override if they support collection management.
+ */
+ @Override
+ public Set findForeignStoreKeySet(T entity, Field foreignStore, Class keyClass) throws DataAccessException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void storeForeignStoreKeySet(T entity, Field foreignStore, Set