diff --git a/build.gradle b/build.gradle
index 3b7f19521..fb5093247 100644
--- a/build.gradle
+++ b/build.gradle
@@ -29,6 +29,9 @@ subprojects {
[compileJava, compileTestJava]*.options*.compilerArgs = ["-Xlint:-serial", "-Xlint:-unchecked"]
+ sourceCompatibility = 1.6
+ targetCompatibility = 1.6
+
dependencies {
groovy "org.codehaus.groovy:groovy:$groovyVersion"
@@ -63,5 +66,5 @@ idea {
project.ipr.withXml { provider ->
provider.node.component.find { it.@name == 'VcsDirectoryMappings' }.mapping.@vcs = 'Git'
}
- module.jdkName = "OpenJDK 1.7"
+ module.jdkName = "1.6"
}
diff --git a/core/build.gradle b/core/build.gradle
index f317c756a..2aa5369b7 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -1,4 +1,4 @@
-archivesBaseName = "spring-data-rest-core"
+archivesBaseName = "${rootProject.name}-${name}"
dependencies {
diff --git a/doc/main_wiki.md b/doc/main_wiki.md
new file mode 100644
index 000000000..8afcae02d
--- /dev/null
+++ b/doc/main_wiki.md
@@ -0,0 +1,155 @@
+# Spring Data JPA Repository Web Exporter
+
+The Spring Data JPA Repository Web Exporter allows you to export your [JPA Repositories](http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/#jpa.repositories) as a RESTful web application. The exporter exposes the CRUD methods of a [CrudRepository](http://static.springsource.org/spring-data/data-commons/docs/1.1.0.RELEASE/api/org/springframework/data/repository/CrudRepository.html) for doing basic entity management. Relationships can also be managed between linked entities. The exporter is deployed as a traditional Spring MVC Controller, which means all the traditional Spring MVC tools are available to work with the Web Exporter (like Spring Security, for instance).
+
+### Installation
+
+Installation is as simple as downloading a WAR file. To expose your Repositories to the exporter, include a Spring XML configuration file in the classpath. The filename should end with "-export.xml" and reside under the path `META-INF/spring-data-rest/`. Your configuration should include a properly-instaniated EntityManagerFactoryBean, an appropriate DataSource, and the appropriate repository configuration. It's easiest to use the special XML namespace for this purpose. An example configuration (named `WEB-INF/spring-data-rest/repositories-export.xml`) would look like something like this:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The file `shared.xml` contains a JDBC DataSource configuration, an EntityManagerFactoryBean, and a JpaTransactionManager.
+
+Of note in this configuration is the bean named `baseUri`. This is the fully-qualified URI at which the exporter is deployed. This tells the exporter what base URI to use when generating links to your entities.
+
+### Including your domain artifacts
+
+To expose your domain objects (your JPA entities, Repositories) and Spring configuration using the web exporter, you need to copy those resources to the web exporter's `WEB-INF/lib` or `WEB-INF/classes` directory. There are potentially other ways to deploy these artifacts without modifying the web exporter's WAR file, but those methods are considerably more complicated and prone to classpath problems. The easiest and most reliable way to deploy your user artifacts are by deploying them alongside the web exporter's artifacts.
+
+### Exposing your repositories
+
+By default, any repositories found are exported using the bean name of the repository in the Spring configuration (minus the word "Repository", if it appears in the bean name).
+
+If you have a JPA entity in your domain model that looks like this:
+
+ @Entity
+ public class Person {
+ @Id
+ private Long id;
+ private String name;
+ @Version
+ private Long version;
+ @OneToMany
+ private List
addresses;
+ @OneToMany
+ private Map profiles;
+ }
+
+An appropriate CrudRepository interface defined like this:
+
+ public interface PersonRepository extends CrudRepository {
+ }
+
+Your PersonRepository will by default be declared in the ApplicationContext with a bean name of "personRepository". The web exporter will strip the word "Repository" from it and expose a resource named "person". The resulting URL of this repository will be `http://localhost:8080/data/person`.
+
+### Discoverability
+
+The Web Exporter implements some aspects of the [HATEOS](http://en.wikipedia.org/wiki/HATEOAS) methodology. That means all the services of the web exporter are discoverable and exposed to the client using links.
+
+If you issue an HTTP request to the root of the exporter:
+
+ curl -v http://localhost:8080/data/
+
+You'll get back a chunk of JSON that points your user agent to the locations of the exposed repositories:
+
+ {
+ "_links" : [{
+ "rel" : "person",
+ "href" : "http://localhost:8080/data/person"
+ }]
+ }
+
+The "rel" of the link will match the exposed name of the repository. Your application should keep track of this rel value as the key to this repository.
+
+Similarly, if you issue a GET to `http://localhost:8080/data/person`, you should get back a list of entities exposed at this resource (as returned by the CrudRepository.findAll method).
+
+ curl -v http://localhost:8080/data/person
+
+ {
+ "_links" : [ {
+ "rel" : "Person",
+ "href" : "http://localhost:8080/data/person/1"
+ }, {
+ "rel" : "Person",
+ "href" : "http://localhost:8080/data/person/2"
+ } ]
+ }
+
+The "rel" of these links will be the simple class name of the entity managed by this repository.
+
+Following these links will give your user agent a chunk of JSON that represents the entity. Besides properly handling nested objects and simple values, the web exporter will show relationships between entities using links just like those presented previously.
+
+ curl -v http://localhost:8080/data/person/1
+
+ {
+ "name" : "John Doe",
+ "_links" : [ {
+ "rel" : "profiles",
+ "href" : "http://localhost:8080/data/person/1/profiles"
+ }, {
+ "rel" : "addresses",
+ "href" : "http://localhost:8080/data/person/1/addresses"
+ }, {
+ "rel" : "self",
+ "href" : "http://localhost:8080/data/person/1"
+ } ],
+ "version" : 1
+ }
+
+This entity has a simple String value called "name", and two relationships to other entities ("profiles", and "addresses"). Note that the "rel" value of the link corresponds to the property name of the @Entity.
+
+The "self" link will always point to the resource for this entity. Use the "self" link to access the entity itself if you wish to update or delete the entity.
+
+Following the links for the "profiles" property, gives us a list of links to the actual entities that are referenced by this relationship:
+
+ curl -v http://localhost:8080/data/person/1/profiles
+
+ {
+ "profiles" : [ {
+ "rel" : "twitter",
+ "href" : "http://localhost:8080/data/person/1/profiles/1"
+ }, {
+ "rel" : "facebook",
+ "href" : "http://localhost:8080/data/person/1/profiles/2"
+ } ]
+ }
+
+Retrieving the linked entity gives us a JSON representation of the entity, as well as the "self" link necessary to update and delete the entity.
+
+ curl -v http://localhost:8080/data/person/1/profiles/1
+
+ {
+ "_links" : [ {
+ "rel" : "self",
+ "href" : "http://localhost:8080/data/profile/1"
+ } ],
+ "type" : "twitter",
+ "url" : "#!/johndoe"
+ }
+
+### Updating relationships
+
+To maintain a relationship between two entities, access the resource of the relationship by using the id of the entity as the last element in the resource path. For example, to add a link to a Profile with id 3 to a Person with id 1, issue a POST to the "profiles" resource and include in the body of the request a list of resource paths to entities you want to link to (make sure to use the special Content-Type "text/uri-list" which, as the name implies, is a representation of a list of URIs):
+
+ curl -v -X POST -H "Content-Type: text/uri-list" -d "http://localhost:8080/data/profile/3" http://localhost:8080/data/person/1/profiles
+
+You can also delete a relationship by issuing a DELETE request to the resource path that represents the relationship between parent and child entities. For example, to delete a relationship between a Profile entity with an id of 2 and a Person with an id of 1:
+
+ curl -v -X DELETE http://localhost:8080/data/person/1/profiles/2
diff --git a/repository/build.gradle b/repository/build.gradle
index bad6e92c3..b33213da0 100644
--- a/repository/build.gradle
+++ b/repository/build.gradle
@@ -1,4 +1,4 @@
-archivesBaseName = "spring-data-rest-repository"
+archivesBaseName = "${rootProject.name}-${name}"
dependencies {
diff --git a/settings.gradle b/settings.gradle
index df8586390..f762b471f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,3 @@
include "core",
"repository",
- "rest"
+ "webmvc"
diff --git a/rest/build.gradle b/webmvc/build.gradle
similarity index 53%
rename from rest/build.gradle
rename to webmvc/build.gradle
index ef2de149b..da98cf84f 100644
--- a/rest/build.gradle
+++ b/webmvc/build.gradle
@@ -1,7 +1,7 @@
-apply plugin: "war"
-apply plugin: "jetty"
+//apply plugin: "war"
+//apply plugin: "jetty"
-archivesBaseName = "spring-data-rest"
+archivesBaseName = "${rootProject.name}-${name}"
dependencies {
@@ -10,15 +10,16 @@ dependencies {
// JPA
compile "org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final"
- compile "org.hibernate:hibernate-entitymanager:$hibernateVersion"
-
- // H2
- compile "org.hsqldb:hsqldb:1.8.0.10"
// Spring
compile "org.springframework:spring-webmvc:$springVersion"
+ runtime "cglib:cglib-nodep:2.2.2"
// Repository Exporter support
compile project(":repository")
+ // Testing
+ testRuntime "org.hibernate:hibernate-entitymanager:$hibernateVersion"
+ testRuntime "org.hsqldb:hsqldb:1.8.0.10"
+
}
diff --git a/rest/src/main/java/org/springframework/data/rest/webmvc/JsonView.java b/webmvc/src/main/java/org/springframework/data/rest/webmvc/JsonView.java
similarity index 100%
rename from rest/src/main/java/org/springframework/data/rest/webmvc/JsonView.java
rename to webmvc/src/main/java/org/springframework/data/rest/webmvc/JsonView.java
diff --git a/rest/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java b/webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java
similarity index 86%
rename from rest/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java
rename to webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java
index 22bec30a2..e18c0d445 100644
--- a/rest/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java
+++ b/webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java
@@ -4,6 +4,7 @@ import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import javax.persistence.EntityManagerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -26,10 +27,13 @@ public class RepositoryRestConfiguration {
@Autowired(required = false)
URI baseUri;
+ @Autowired
+ EntityManagerFactory entityManagerFactory;
@Autowired(required = false)
JpaRepositoryMetadata jpaRepositoryMetadata;
@Autowired(required = false)
- ConversionService conversionService;
+ ConversionService customConversionService;
+ ConversionService defaultConversionService = new DefaultConversionService();
@Autowired(required = false)
List> httpMessageConverters = new ArrayList>();
@@ -41,10 +45,11 @@ public class RepositoryRestConfiguration {
}
@Bean ConversionService conversionService() {
- if (null == conversionService) {
- conversionService = new DefaultConversionService();
+ if (null != customConversionService) {
+ return customConversionService;
+ } else {
+ return defaultConversionService;
}
- return conversionService;
}
@Bean List> httpMessageConverters() {
diff --git a/rest/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java b/webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java
similarity index 100%
rename from rest/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java
rename to webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java
diff --git a/rest/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java b/webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java
similarity index 75%
rename from rest/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java
rename to webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java
index ed1abc001..e4a1b1435 100644
--- a/rest/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java
+++ b/webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java
@@ -1,12 +1,24 @@
package org.springframework.data.rest.webmvc;
+import java.net.URI;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import javax.persistence.EntityManagerFactory;
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;
+import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
+import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
@@ -23,7 +35,7 @@ import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
public class RepositoryRestMvcConfiguration {
@Autowired
- RepositoryRestConfiguration repositoryRestConfiguration;
+ RepositoryRestConfiguration parentConfig;
RepositoryRestController repositoryRestController;
@Bean ContentNegotiatingViewResolver contentNegotiatingViewResolver() {
@@ -46,10 +58,10 @@ public class RepositoryRestMvcConfiguration {
@Bean RepositoryRestController repositoryRestController() throws Exception {
if (null == repositoryRestController) {
this.repositoryRestController = new RepositoryRestController()
- .baseUri(repositoryRestConfiguration.baseUri())
- .repositoryMetadata(repositoryRestConfiguration.jpaRepositoryMetadata())
- .conversionService(repositoryRestConfiguration.conversionService())
- .httpMessageConverters(repositoryRestConfiguration.httpMessageConverters())
+ .baseUri(parentConfig.baseUri())
+ .repositoryMetadata(parentConfig.jpaRepositoryMetadata())
+ .conversionService(parentConfig.conversionService())
+ .httpMessageConverters(parentConfig.httpMessageConverters())
.jsonMediaType("application/json");
}
return repositoryRestController;
diff --git a/rest/src/main/java/org/springframework/data/rest/webmvc/ServerHttpRequestMethodArgumentResolver.java b/webmvc/src/main/java/org/springframework/data/rest/webmvc/ServerHttpRequestMethodArgumentResolver.java
similarity index 100%
rename from rest/src/main/java/org/springframework/data/rest/webmvc/ServerHttpRequestMethodArgumentResolver.java
rename to webmvc/src/main/java/org/springframework/data/rest/webmvc/ServerHttpRequestMethodArgumentResolver.java
diff --git a/rest/src/main/java/org/springframework/data/rest/webmvc/UriListView.java b/webmvc/src/main/java/org/springframework/data/rest/webmvc/UriListView.java
similarity index 100%
rename from rest/src/main/java/org/springframework/data/rest/webmvc/UriListView.java
rename to webmvc/src/main/java/org/springframework/data/rest/webmvc/UriListView.java
diff --git a/rest/src/main/webapp/WEB-INF/web.xml b/webmvc/src/main/webapp/WEB-INF/web.xml
similarity index 89%
rename from rest/src/main/webapp/WEB-INF/web.xml
rename to webmvc/src/main/webapp/WEB-INF/web.xml
index ad7d31d4b..d6b051aaf 100644
--- a/rest/src/main/webapp/WEB-INF/web.xml
+++ b/webmvc/src/main/webapp/WEB-INF/web.xml
@@ -10,17 +10,13 @@
contextConfigLocation
- org.springframework.data.rest.mvc.RepositoryRestConfiguration
+ org.springframework.data.rest.webmvc.RepositoryRestConfiguration
+
org.springframework.web.context.ContextLoaderListener
-
- entityManagerInViewFilter
- org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
-
-
exporter
org.springframework.web.servlet.DispatcherServlet
@@ -30,11 +26,16 @@
contextConfigLocation
- org.springframework.data.rest.mvc.RepositoryRestMvcConfiguration
+ org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration
1
+
+ entityManagerInViewFilter
+ org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
+
+
entityManagerInViewFilter
exporter
diff --git a/rest/src/test/groovy/org/springframework/data/rest/webmvc/spec/RepositoryRestControllerSpec.groovy b/webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RepositoryRestControllerSpec.groovy
similarity index 100%
rename from rest/src/test/groovy/org/springframework/data/rest/webmvc/spec/RepositoryRestControllerSpec.groovy
rename to webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RepositoryRestControllerSpec.groovy
diff --git a/rest/src/test/java/org/springframework/data/rest/test/RestBuilder.java b/webmvc/src/test/java/org/springframework/data/rest/test/RestBuilder.java
similarity index 100%
rename from rest/src/test/java/org/springframework/data/rest/test/RestBuilder.java
rename to webmvc/src/test/java/org/springframework/data/rest/test/RestBuilder.java
diff --git a/rest/src/test/java/org/springframework/data/rest/test/webmvc/Address.java b/webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Address.java
similarity index 100%
rename from rest/src/test/java/org/springframework/data/rest/test/webmvc/Address.java
rename to webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Address.java
diff --git a/rest/src/test/java/org/springframework/data/rest/test/webmvc/AddressRepository.java b/webmvc/src/test/java/org/springframework/data/rest/test/webmvc/AddressRepository.java
similarity index 100%
rename from rest/src/test/java/org/springframework/data/rest/test/webmvc/AddressRepository.java
rename to webmvc/src/test/java/org/springframework/data/rest/test/webmvc/AddressRepository.java
diff --git a/rest/src/test/java/org/springframework/data/rest/test/webmvc/Person.java b/webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Person.java
similarity index 100%
rename from rest/src/test/java/org/springframework/data/rest/test/webmvc/Person.java
rename to webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Person.java
diff --git a/rest/src/test/java/org/springframework/data/rest/test/webmvc/PersonLoader.java b/webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonLoader.java
similarity index 100%
rename from rest/src/test/java/org/springframework/data/rest/test/webmvc/PersonLoader.java
rename to webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonLoader.java
diff --git a/rest/src/test/java/org/springframework/data/rest/test/webmvc/PersonRepository.java b/webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonRepository.java
similarity index 100%
rename from rest/src/test/java/org/springframework/data/rest/test/webmvc/PersonRepository.java
rename to webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonRepository.java
diff --git a/rest/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java b/webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java
similarity index 100%
rename from rest/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java
rename to webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java
diff --git a/rest/src/test/java/org/springframework/data/rest/test/webmvc/ProfileRepository.java b/webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ProfileRepository.java
similarity index 100%
rename from rest/src/test/java/org/springframework/data/rest/test/webmvc/ProfileRepository.java
rename to webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ProfileRepository.java
diff --git a/rest/src/test/resources/META-INF/persistence.xml b/webmvc/src/test/resources/META-INF/persistence.xml
similarity index 100%
rename from rest/src/test/resources/META-INF/persistence.xml
rename to webmvc/src/test/resources/META-INF/persistence.xml
diff --git a/rest/src/test/resources/META-INF/spring-data-rest/repositories-export.xml b/webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml
similarity index 100%
rename from rest/src/test/resources/META-INF/spring-data-rest/repositories-export.xml
rename to webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml
diff --git a/rest/src/test/resources/META-INF/spring-data-rest/shared.xml b/webmvc/src/test/resources/META-INF/spring-data-rest/shared.xml
similarity index 100%
rename from rest/src/test/resources/META-INF/spring-data-rest/shared.xml
rename to webmvc/src/test/resources/META-INF/spring-data-rest/shared.xml
index 522ed1555..5b2a67d19 100644
--- a/rest/src/test/resources/META-INF/spring-data-rest/shared.xml
+++ b/webmvc/src/test/resources/META-INF/spring-data-rest/shared.xml
@@ -9,6 +9,8 @@
+
+
@@ -24,6 +26,4 @@
-
-
\ No newline at end of file
diff --git a/rest/src/test/resources/logback.xml b/webmvc/src/test/resources/logback.xml
similarity index 100%
rename from rest/src/test/resources/logback.xml
rename to webmvc/src/test/resources/logback.xml