From 749382dad705a7c7092c9a0d8b25373f6d53529c Mon Sep 17 00:00:00 2001 From: Jon Brisbin Date: Wed, 2 May 2012 16:24:53 -0500 Subject: [PATCH] Documentation on handling events. Also added support for Spring Data Commons 1.3.0.RC2, which has improved metadata handling. --- build.gradle | 2 + doc/handling_events.md | 111 ++++++++++++++++++ gradle.properties | 4 +- .../rest/repository/RepositoryExporter.java | 38 ++---- .../rest/repository/RepositoryMetadata.java | 9 +- .../repository/context/AfterDeleteEvent.java | 2 + .../context/AfterLinkSaveEvent.java | 2 + .../repository/context/AfterSaveEvent.java | 4 +- ...notatedHandlerRepositoryEventListener.java | 7 ++ .../repository/context/BeforeDeleteEvent.java | 4 +- .../context/BeforeLinkSaveEvent.java | 2 + .../repository/context/BeforeSaveEvent.java | 4 +- .../repository/context/LinkSaveEvent.java | 9 +- .../repository/jpa/JpaRepositoryExporter.java | 21 +--- .../repository/jpa/JpaRepositoryMetadata.java | 56 ++++----- .../test/resources/ExtensionsSpec-test.xml | 6 +- .../rest/webmvc/RepositoryRestController.java | 1 - .../spec/RepositoryRestControllerSpec.groovy | 8 +- 18 files changed, 191 insertions(+), 99 deletions(-) create mode 100644 doc/handling_events.md 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, - E extends EntityMetadata> +public abstract class RepositoryExporter, E extends EntityMetadata> 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> { +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> repositoryClass(); + Class repositoryClass(); /** * The {@link Repository} instance. * * @return */ - R repository(); + CrudRepository repository(); /** * The {@link EntityMetadata} associated with the domain type of this {@literal Repository}. diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterDeleteEvent.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterDeleteEvent.java index e315be688..5e93ede21 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterDeleteEvent.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterDeleteEvent.java @@ -1,6 +1,8 @@ package org.springframework.data.rest.repository.context; /** + * Emitted after the entity is delete from the repository. + * * @author Jon Brisbin */ public class AfterDeleteEvent extends RepositoryEvent { diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterLinkSaveEvent.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterLinkSaveEvent.java index bd0eaa3e3..b316f9841 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterLinkSaveEvent.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterLinkSaveEvent.java @@ -1,6 +1,8 @@ package org.springframework.data.rest.repository.context; /** + * Emitted immediately after saving a linked object to its parent in the repository. + * * @author Jon Brisbin */ public class AfterLinkSaveEvent extends LinkSaveEvent { diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterSaveEvent.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterSaveEvent.java index 64b440345..3df0d9eca 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterSaveEvent.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AfterSaveEvent.java @@ -1,8 +1,8 @@ package org.springframework.data.rest.repository.context; -import org.springframework.context.ApplicationEvent; - /** + * Emitted immediately after a save to the repository. + * * @author Jon Brisbin */ public class AfterSaveEvent extends RepositoryEvent { diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AnnotatedHandlerRepositoryEventListener.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AnnotatedHandlerRepositoryEventListener.java index f2a25b07e..ed495e409 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AnnotatedHandlerRepositoryEventListener.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/AnnotatedHandlerRepositoryEventListener.java @@ -41,6 +41,13 @@ public class AnnotatedHandlerRepositoryEventListener private ApplicationContext applicationContext; private Multimap, EventHandlerMethod> handlerMethods = ArrayListMultimap.create(); + public AnnotatedHandlerRepositoryEventListener() { + } + + public AnnotatedHandlerRepositoryEventListener(String basePackage) { + this.basePackage = basePackage; + } + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeDeleteEvent.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeDeleteEvent.java index 727579c10..ee61acedb 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeDeleteEvent.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeDeleteEvent.java @@ -1,8 +1,8 @@ package org.springframework.data.rest.repository.context; -import org.springframework.context.ApplicationEvent; - /** + * Emitted before an entity is deleted from the repository. + * * @author Jon Brisbin */ public class BeforeDeleteEvent extends RepositoryEvent { diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeLinkSaveEvent.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeLinkSaveEvent.java index 99ff72d7d..34991125b 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeLinkSaveEvent.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeLinkSaveEvent.java @@ -1,6 +1,8 @@ package org.springframework.data.rest.repository.context; /** + * Emitted before a linked object is saved to the repository. + * * @author Jon Brisbin */ public class BeforeLinkSaveEvent extends LinkSaveEvent { diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeSaveEvent.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeSaveEvent.java index 0a242e941..ddcfa2408 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeSaveEvent.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/BeforeSaveEvent.java @@ -1,8 +1,8 @@ package org.springframework.data.rest.repository.context; -import org.springframework.context.ApplicationEvent; - /** + * Emitted before an entity is saved into the repository. + * * @author Jon Brisbin */ public class BeforeSaveEvent extends RepositoryEvent { diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/LinkSaveEvent.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/LinkSaveEvent.java index 6b4f05f44..3bcdf8a20 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/LinkSaveEvent.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/LinkSaveEvent.java @@ -1,9 +1,11 @@ package org.springframework.data.rest.repository.context; /** + * Base class for {@link RepositoryEvent}s that deal with saving a linked object. + * * @author Jon Brisbin */ -public class LinkSaveEvent extends RepositoryEvent { +public abstract class LinkSaveEvent extends RepositoryEvent { private final Object linked; @@ -12,6 +14,11 @@ public class LinkSaveEvent extends RepositoryEvent { this.linked = linked; } + /** + * Get the linked object. + * + * @return + */ public Object getLinked() { return linked; } diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/jpa/JpaRepositoryExporter.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/jpa/JpaRepositoryExporter.java index 5c71268f9..b43ff5e2f 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/jpa/JpaRepositoryExporter.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/jpa/JpaRepositoryExporter.java @@ -1,11 +1,10 @@ package org.springframework.data.rest.repository.jpa; -import java.io.Serializable; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.data.repository.Repository; -import org.springframework.data.repository.core.EntityInformation; +import org.springframework.data.repository.support.Repositories; import org.springframework.data.rest.repository.RepositoryExporter; /** @@ -13,10 +12,7 @@ import org.springframework.data.rest.repository.RepositoryExporter; * * @author Jon Brisbin */ -public class JpaRepositoryExporter extends RepositoryExporter< - JpaRepositoryMetadata>, - Repository, - JpaEntityMetadata> { +public class JpaRepositoryExporter extends RepositoryExporter { protected EntityManager entityManager; @@ -27,17 +23,8 @@ public class JpaRepositoryExporter extends RepositoryExporter< @SuppressWarnings({"unchecked"}) @Override - protected JpaRepositoryMetadata> createRepositoryMetadata( - Class repoClass, - Repository repo, - String name, - EntityInformation entityInfo) { - return new JpaRepositoryMetadata(repositories, - name, - repoClass, - repo, - entityInfo, - entityManager); + protected JpaRepositoryMetadata createRepositoryMetadata(String name, Class domainType, Class repoClass, Repositories repositories) { + return new JpaRepositoryMetadata(name, domainType, repoClass, repositories, entityManager); } } diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/jpa/JpaRepositoryMetadata.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/jpa/JpaRepositoryMetadata.java index a0bf66af3..b424c6c99 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/jpa/JpaRepositoryMetadata.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/jpa/JpaRepositoryMetadata.java @@ -8,7 +8,7 @@ import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.metamodel.Metamodel; -import org.springframework.data.repository.Repository; +import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.core.EntityInformation; import org.springframework.data.repository.support.Repositories; import org.springframework.data.rest.repository.RepositoryMetadata; @@ -20,11 +20,11 @@ import org.springframework.util.StringUtils; /** * @author Jon Brisbin */ -public class JpaRepositoryMetadata> implements RepositoryMetadata { +public class JpaRepositoryMetadata implements RepositoryMetadata { private final String name; - private final Class> repoClass; - private final R repository; + private final Class repoClass; + private final CrudRepository repository; private final EntityInformation entityInfo; private final Map queryMethods = new HashMap(); @@ -32,16 +32,15 @@ public class JpaRepositoryMetadata> i private JpaEntityMetadata entityMetadata; @SuppressWarnings({"unchecked"}) - public JpaRepositoryMetadata(Repositories repositories, - String name, - final Class> repoClass, - R repository, - EntityInformation entityInfo, + public JpaRepositoryMetadata(String name, + Class domainType, + final Class repoClass, + Repositories repositories, EntityManager entityManager) { this.name = name; this.repoClass = repoClass; - this.repository = repository; - this.entityInfo = entityInfo; + this.repository = repositories.getRepositoryFor(domainType); + this.entityInfo = repositories.getEntityInformationFor(domainType); RestResource resourceAnno = repoClass.getAnnotation(RestResource.class); if (null != resourceAnno && StringUtils.hasText(resourceAnno.rel())) { @@ -50,26 +49,15 @@ public class JpaRepositoryMetadata> i rel = name; } - ReflectionUtils.doWithMethods( - repoClass, - new ReflectionUtils.MethodCallback() { - @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - RestResource resourceAnno = method.getAnnotation(RestResource.class); - String pathSeg = resourceAnno.path(); - ReflectionUtils.makeAccessible(method); - queryMethods.put(pathSeg, new RepositoryQueryMethod(method)); - } - }, - new ReflectionUtils.MethodFilter() { - @Override public boolean matches(Method method) { - return (!method.isSynthetic() - && !method.isBridge() - && method.getDeclaringClass() != Object.class - && !method.getName().contains("$") - && null != method.getAnnotation(RestResource.class)); - } - } - ); + for (Method method : repositories.getRepositoryInformationFor(domainType).getQueryMethods()) { + String pathSeg = method.getName(); + RestResource methodResourceAnno = method.getAnnotation(RestResource.class); + if (null != methodResourceAnno) { + pathSeg = methodResourceAnno.path(); + } + ReflectionUtils.makeAccessible(method); + queryMethods.put(pathSeg, new RepositoryQueryMethod(method)); + } Metamodel metamodel = entityManager.getMetamodel(); entityMetadata = new JpaEntityMetadata(repositories, metamodel.entity(entityInfo.getJavaType())); @@ -83,15 +71,15 @@ public class JpaRepositoryMetadata> i return rel; } - @Override public Class domainType() { + @Override public Class domainType() { return entityMetadata.type(); } - @Override public Class> repositoryClass() { + @Override public Class repositoryClass() { return repoClass; } - @Override public R repository() { + @Override public CrudRepository repository() { return repository; } diff --git a/spring-data-rest-repository/src/test/resources/ExtensionsSpec-test.xml b/spring-data-rest-repository/src/test/resources/ExtensionsSpec-test.xml index b37321f86..89016685e 100644 --- a/spring-data-rest-repository/src/test/resources/ExtensionsSpec-test.xml +++ b/spring-data-rest-repository/src/test/resources/ExtensionsSpec-test.xml @@ -1,12 +1,12 @@ - + + + \ No newline at end of file diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java index 688207592..a94a53956 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java @@ -58,7 +58,6 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.server.ServerHttpRequest; import org.springframework.stereotype.Controller; -import org.springframework.transaction.annotation.Transactional; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; import org.springframework.util.Assert; diff --git a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RepositoryRestControllerSpec.groovy b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RepositoryRestControllerSpec.groovy index d4b09878d..de2a06846 100644 --- a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RepositoryRestControllerSpec.groovy +++ b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RepositoryRestControllerSpec.groovy @@ -16,7 +16,6 @@ import org.springframework.mock.web.MockHttpServletRequest import org.springframework.mock.web.MockServletConfig import org.springframework.mock.web.MockServletContext import org.springframework.orm.jpa.EntityManagerHolder -import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.support.TransactionSynchronizationManager import org.springframework.ui.ExtendedModelMap import org.springframework.web.context.support.AnnotationConfigWebApplicationContext @@ -75,7 +74,6 @@ class RepositoryRestControllerSpec extends Specification { } } - @Transactional def "API Test"() { given: @@ -99,7 +97,7 @@ class RepositoryRestControllerSpec extends Specification { then: model.status == HttpStatus.CREATED - when: "getting specific entity" + when: "getting a specific entity" model.clear() req = createRequest("GET", "people/1") controller.entity(new ServletServerHttpRequest(req), uriBuilder, "people", "1", model) @@ -126,7 +124,7 @@ class RepositoryRestControllerSpec extends Specification { model.status == HttpStatus.OK peopleLinks[0].href().toString() == "http://localhost:8080/data/people/1" - when: "creating child entity" + when: "creating a child entity" model.clear() req = createRequest("POST", "address") data = mapper.writeValueAsBytes(new Address(["1 W. 1st St."] as String[], "Univille", "ST", "12345")) @@ -147,7 +145,7 @@ class RepositoryRestControllerSpec extends Specification { then: model.status == HttpStatus.CREATED - when: "getting property of entity" + when: "getting property of an entity" model.clear() controller.propertyOfEntity(uriBuilder, "people", "1", "addresses", model) def addrLinks = model.resource?.links