diff --git a/build.gradle b/build.gradle
index 42217cc73..7a409bd61 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,9 +11,11 @@ allprojects {
exclude group: "commons-logging"
exclude module: "slf4j-log4j12"
exclude module: "groovy-all", version: "1.8.0-beta-3-SNAPSHOT"
+ resolutionStrategy.cacheChangingModulesFor(0, "seconds")
}
repositories {
+ maven { url "http://repo.springsource.org/libs-snapshot" }
maven { url "http://repo.springsource.org/libs-milestone" }
maven { url "http://repo.springsource.org/libs-release" }
}
diff --git a/doc/handling_events.md b/doc/handling_events.md
new file mode 100644
index 000000000..22b5d22f3
--- /dev/null
+++ b/doc/handling_events.md
@@ -0,0 +1,111 @@
+# Handling ApplicationEvents in the REST Exporter
+
+There are six different events that the REST exporter emits throughout the process of working with an entity. Those are:
+
+* BeforeSaveEvent
+* AfterSaveEvent
+* BeforeLinkSaveEvent
+* AfterLinkSaveEvent
+* BeforeDeleteEvent
+* AfterDeleteEvent
+
+### ApplicationListener
+
+There is an abstract class you can subclass which listens for these kinds of events and calls
+the appropriate method based on the event type. You just override the methods for
+the events you're interested in.
+
+ public class BeforeSaveEventListener extends AbstractRepositoryEventListener {
+
+ @Override public void onBeforeSave(Object entity) {
+ ... logic to handle inspecting the entity before the Repository saves it
+ }
+
+ @Override public void onAfterDelete(Object entity) {
+ ... send a message that this entity has been deleted
+ }
+
+ }
+
+One thing to note with this approach, however, is that it makes no distinction based on
+the type of the entity. You'll have to inspect that yourself.
+
+### Annotated Handler
+
+Another approach is to use an annotated handler, which does filter events based on domain type.
+
+To declare a handler, create a POJO and put the `@RepositoryEventHandler` annotation on it.
+This tells the classpath scanner that this class needs to be inspected for handler methods.
+
+Once it finds a class with this annotation, it iterates over the exposed methods and looks for
+annotations that correspond to the event you're interested in. For example, to handle BeforeSaveEvents
+in an annotated POJO for different kinds of domain types, you'd define your class like this:
+
+ @RepositoryEventHandler
+ public class PersonEventHandler {
+
+ @HandleBeforeSave(Person.class) public void handlePersonSave(Person p) {
+ ... you can now deal with Person in a type-safe way
+ }
+
+ @HandleBeforeSave(Profile.class) public void handleProfileSave(Profile p) {
+ ... you can now deal with Profile in a type-safe way
+ }
+
+ }
+
+You can also declare the domain type at the class level:
+
+ @RepositoryEventHandler(Person.class)
+ public class PersonEventHandler {
+
+ @HandleBeforeSave public void handleBeforeSave(Person p) {
+ ...
+ }
+
+ @HandleAfterDelete public void handleAfterDelete(Person p) {
+ ...
+ }
+
+ }
+
+To actually get your handler invoked, however, you need to declare an instance of it in your
+ApplicationContext. The classpath scanner will look for event handlers and build up information
+about them, but it won't actually wire a handler to accept events unless there's an instance of
+it declared in your ApplicationContext.
+
+(In JavaConfig style):
+
+ @Configuration
+ public class RepositoryConfiguration {
+
+ @Bean PersonEventHandler personEventHandler() {
+ return new PersonEventHandler();
+ }
+
+ }
+
+When you have your beans properly declared, you need to declare an instance of the ApplicationListener.
+You can pass the base package of the packages you want searched for handlers in the constructor.
+
+ @Configuration
+ public class RepositoryConfiguration {
+
+ @Bean PersonEventHandler personEventHandler() {
+ return new PersonEventHandler();
+ }
+
+ @Bean AnnotatedHandlerRepositoryEventListener repositoryEventListener() {
+ return new AnnotatedHandlerRepositoryEventListener("com.mycompany.repository.handlers");
+ }
+
+ }
+
+(In XML style):
+
+
+
+
+
+
+
diff --git a/gradle.properties b/gradle.properties
index ad3d92b63..54b79fb28 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -10,8 +10,8 @@ cglibVersion = 2.2
groovyVersion = 1.8.6
# Supporting libraries
-sdCommonsVersion = 1.3.0.RC1
-sdJpaVersion = 1.1.0.RC1
+sdCommonsVersion = 1.3.0.RC2
+sdJpaVersion = 1.1.0.BUILD-SNAPSHOT
jacksonVersion = 1.9.5
hibernateVersion = 4.1.1.Final
diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryExporter.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryExporter.java
index 92375e65d..b70771c83 100644
--- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryExporter.java
+++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryExporter.java
@@ -1,7 +1,5 @@
package org.springframework.data.rest.repository;
-import java.io.Serializable;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -9,13 +7,9 @@ import java.util.Map;
import java.util.Set;
import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
-import org.springframework.data.repository.Repository;
-import org.springframework.data.repository.core.EntityInformation;
-import org.springframework.data.repository.core.support.RepositoryFactoryInformation;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.repository.annotation.RestResource;
import org.springframework.util.StringUtils;
@@ -26,9 +20,7 @@ import org.springframework.util.StringUtils;
*
* @author Jon Brisbin
*/
-public abstract class RepositoryExporter,
- R extends Repository extends Object, ? extends Serializable>,
- E extends EntityMetadata extends AttributeMetadata>>
+public abstract class RepositoryExporter, E extends EntityMetadata extends AttributeMetadata>>
implements ApplicationContextAware,
InitializingBean {
@@ -67,14 +59,12 @@ public abstract class RepositoryExporter,
@Override public void afterPropertiesSet() throws Exception {
repositories = new Repositories(applicationContext);
repositoryMetadata = new HashMap();
- Collection providers = BeanFactoryUtils.beansOfTypeIncludingAncestors(
- applicationContext,
- RepositoryFactoryInformation.class
- ).values();
-
- for (RepositoryFactoryInformation entry : providers) {
- EntityInformation entityInfo = entry.getEntityInformation();
- Class> repoClass = entry.getRepositoryInterface();
+ for (Class> domainType : repositories) {
+ if (!exportOnlyTheseClasses.isEmpty() && !exportOnlyTheseClasses.contains(domainType.getName())) {
+ // Don't export this domain type
+ continue;
+ }
+ Class> repoClass = repositories.getRepositoryInformationFor(domainType).getRepositoryInterface();
String name;
RestResource pathSeg = repoClass.getAnnotation(RestResource.class);
if (null != pathSeg) {
@@ -82,9 +72,7 @@ public abstract class RepositoryExporter,
} else {
name = StringUtils.uncapitalize(repoClass.getSimpleName().replaceAll("Repository", ""));
}
- R repo = (R) BeanFactoryUtils.beanOfTypeIncludingAncestors(applicationContext, repoClass);
- M repoMeta = createRepositoryMetadata(repoClass, repo, name, entityInfo);
- repositoryMetadata.put(name, repoMeta);
+ repositoryMetadata.put(name, createRepositoryMetadata(name, domainType, repoClass, repositories));
}
}
@@ -137,11 +125,9 @@ public abstract class RepositoryExporter,
return repositoryMetadata.get(name);
}
- protected abstract M createRepositoryMetadata(
- Class repoClass,
- R repo,
- String name,
- EntityInformation entityInfo
- );
+ protected abstract M createRepositoryMetadata(String name,
+ Class> domainType,
+ Class> repoClass,
+ Repositories repositories);
}
diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryMetadata.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryMetadata.java
index 4718c02ad..b6f376d66 100644
--- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryMetadata.java
+++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryMetadata.java
@@ -3,6 +3,7 @@ package org.springframework.data.rest.repository;
import java.io.Serializable;
import java.util.Map;
+import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.Repository;
/**
@@ -10,7 +11,7 @@ import org.springframework.data.repository.Repository;
*
* @author Jon Brisbin
*/
-public interface RepositoryMetadata, E extends EntityMetadata extends AttributeMetadata>> {
+public interface RepositoryMetadata> {
/**
* The name this {@link Repository} is exported under.
@@ -31,21 +32,21 @@ public interface RepositoryMetadata domainType();
+ Class> domainType();
/**
* The Class of the {@link Repository} subinterface.
*
* @return
*/
- Class extends Repository extends Object, ? extends Serializable>> repositoryClass();
+ Class> repositoryClass();
/**
* The {@link Repository} instance.
*
* @return
*/
- R repository();
+ CrudRepository