diff --git a/README.md b/README.md new file mode 100644 index 000000000..f8691be62 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# Spring Data Rest Exporter + +The Spring Data Rest exporter is a project that aims to make it easy to expose various +services as Rest endpoints. The goal of the project is to provide a flexible and configurable +mechanism for writing simple services that can expose arbitrary services over HTTP. + +The first exporter implemented is a JPA Repository exporter. This takes your JPA repositories +and front-ends them with HTTP, allowing you full CRUD capability over your entities, to include +managing associations. + +### Installation + +To use the Spring Data Rest exporter, first package your domain classes and repositories into a JAR +file. Include some Spring XML configuration files in the `META-INF/spring-data-rest` directory in +that JAR file (including an applicable EntityManager and DataSource). + +You can either deploy this JAR file into your Servlet container in a "shared" configuration, or you +can add this JAR file (and any other application dependencies to the exporter WAR file's `WEB-INF/lib` +directory. diff --git a/core/build.gradle b/core/build.gradle index 1b01ab021..f317c756a 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,3 +1,5 @@ +archivesBaseName = "spring-data-rest-core" + dependencies { // Google Guava diff --git a/core/src/test/groovy/org/springframework/data/rest/core/UriUtilsSpec.groovy b/core/src/test/groovy/org/springframework/data/rest/core/spec/UriUtilsSpec.groovy similarity index 96% rename from core/src/test/groovy/org/springframework/data/rest/core/UriUtilsSpec.groovy rename to core/src/test/groovy/org/springframework/data/rest/core/spec/UriUtilsSpec.groovy index 60910deb8..d9afdb0d6 100644 --- a/core/src/test/groovy/org/springframework/data/rest/core/UriUtilsSpec.groovy +++ b/core/src/test/groovy/org/springframework/data/rest/core/spec/UriUtilsSpec.groovy @@ -1,4 +1,4 @@ -package org.springframework.data.rest.core +package org.springframework.data.rest.core.spec import org.springframework.data.rest.core.util.UriUtils import spock.lang.Specification diff --git a/repository/build.gradle b/repository/build.gradle index 4b8a8c85a..bad6e92c3 100644 --- a/repository/build.gradle +++ b/repository/build.gradle @@ -1,3 +1,5 @@ +archivesBaseName = "spring-data-rest-repository" + dependencies { // Spring diff --git a/repository/src/test/groovy/org/springframework/data/rest/repository/spec/JpaMetadataSpec.groovy b/repository/src/test/groovy/org/springframework/data/rest/repository/spec/JpaMetadataSpec.groovy new file mode 100644 index 000000000..7a09905ab --- /dev/null +++ b/repository/src/test/groovy/org/springframework/data/rest/repository/spec/JpaMetadataSpec.groovy @@ -0,0 +1,64 @@ +package org.springframework.data.rest.repository.spec + +import javax.persistence.Entity +import javax.persistence.EntityManager +import javax.persistence.GeneratedValue +import javax.persistence.Id +import javax.persistence.PersistenceContext +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.ApplicationContext +import org.springframework.data.repository.CrudRepository +import org.springframework.data.rest.repository.JpaRepositoryMetadata +import org.springframework.test.context.ContextConfiguration +import spock.lang.Specification + +/** + * @author Jon Brisbin + */ +@ContextConfiguration(locations = ["/JpaMetadataSpec-test.xml"]) +class JpaMetadataSpec extends Specification { + + @Autowired + ApplicationContext applicationContext + @PersistenceContext + EntityManager entityManager + @Autowired + Collection repositories + JpaRepositoryMetadata repoMeta + + def setup() { + repoMeta = new JpaRepositoryMetadata( + repositories: repositories, + applicationContext: applicationContext, + entityManager: entityManager + ) + repoMeta.afterPropertiesSet() + } + + def "finds repositories in ApplicationContext"() { + + when: + def repo = repoMeta.repositoryFor("simple") + + then: + null != repo + repo instanceof SimpleRepository + + when: + repo = repoMeta.repositoryFor(Simple) + + then: + null != repo + repo instanceof SimpleRepository + + } + +} + +@Entity +class Simple { + @Id @GeneratedValue Long id + String name +} + +interface SimpleRepository extends CrudRepository {} diff --git a/repository/src/test/resources/JpaMetadataSpec-persistence.xml b/repository/src/test/resources/JpaMetadataSpec-persistence.xml new file mode 100644 index 000000000..abaac1ce0 --- /dev/null +++ b/repository/src/test/resources/JpaMetadataSpec-persistence.xml @@ -0,0 +1,14 @@ + + + + org.springframework.data.rest.repository.spec.Simple + + + + + + + + + + \ No newline at end of file diff --git a/repository/src/test/resources/JpaMetadataSpec-test.xml b/repository/src/test/resources/JpaMetadataSpec-test.xml new file mode 100644 index 000000000..988ff37af --- /dev/null +++ b/repository/src/test/resources/JpaMetadataSpec-test.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rest/build.gradle b/rest/build.gradle index afc9cf583..37e3fdc8b 100644 --- a/rest/build.gradle +++ b/rest/build.gradle @@ -1,6 +1,8 @@ apply plugin: "war" apply plugin: "jetty" +archivesBaseName = "spring-data-rest" + dependencies { // APIS diff --git a/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestConfiguration.java b/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestConfiguration.java index 1f5672703..4d6b09c2c 100644 --- a/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestConfiguration.java +++ b/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestConfiguration.java @@ -9,6 +9,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.rest.repository.JpaRepositoryMetadata; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; @@ -27,6 +29,8 @@ public class RepositoryRestConfiguration { @Autowired(required = false) JpaRepositoryMetadata jpaRepositoryMetadata; @Autowired(required = false) + ConversionService conversionService; + @Autowired(required = false) List> httpMessageConverters = new ArrayList>(); @Bean URI baseUri() { @@ -36,6 +40,13 @@ public class RepositoryRestConfiguration { return baseUri; } + @Bean ConversionService conversionService() { + if (null == conversionService) { + conversionService = new DefaultConversionService(); + } + return conversionService; + } + @Bean List> httpMessageConverters() { if (httpMessageConverters.isEmpty()) { MappingJacksonHttpMessageConverter json = new MappingJacksonHttpMessageConverter(); diff --git a/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestController.java b/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestController.java index 4633b112b..75b224fd5 100644 --- a/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestController.java +++ b/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestController.java @@ -342,7 +342,7 @@ public class RepositoryRestController implements InitializingBean { model.addAttribute(RESOURCE, child); } } - } else if (uriCnt == 4) { + } else { final String childId = UriUtils.path(uris.get(3)); Class childIdType = childEntityInfo.getIdType(); final Serializable childSerId; diff --git a/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestMvcConfiguration.java b/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestMvcConfiguration.java index 6a4bfb31c..6b4350ded 100644 --- a/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestMvcConfiguration.java +++ b/rest/src/main/java/org/springframework/data/rest/mvc/RepositoryRestMvcConfiguration.java @@ -48,6 +48,7 @@ public class RepositoryRestMvcConfiguration { this.repositoryRestController = new RepositoryRestController() .baseUri(repositoryRestConfiguration.baseUri()) .repositoryMetadata(repositoryRestConfiguration.jpaRepositoryMetadata()) + .conversionService(repositoryRestConfiguration.conversionService()) .httpMessageConverters(repositoryRestConfiguration.httpMessageConverters()) .jsonMediaType("application/json"); }