Added test coverage, updated the README to reflect a sample configuration.

This commit is contained in:
Jon Brisbin
2012-03-12 09:24:08 -05:00
parent b68c16eab2
commit 26a52332ae
3 changed files with 173 additions and 14 deletions

View File

@@ -11,9 +11,69 @@ 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).
file. Include some Spring XML configuration files in the `META-INF/spring-data-rest` directory (the
file name should end with "-export.xml" to be picked up by the scanner) in that JAR file that include
an applicable EntityManager and DataSource and the Repository configuration (using the special JPA
Repository namespace).
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`
can add this JAR file (and any other application dependencies) to the exporter WAR file's `WEB-INF/lib`
directory.
Somewhere in the Spring configuration files you need to define a bean called "baseUri" that is a
`java.net.URI` and is the fully-qualified URI in which the exporter servlet has been deployed. In the
case of the sample below, the servlet is deployed to a context path of `/data`. Using the default
host and port settings, this yields a `baseUri` of `http://localhost:8080/data`. You'll want to change
this to reflect your deployment configuration.
### Sample Configuration
The configuration used in testing looks like this:
##### META-INF/spring-data-rest/shared.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<bean id="baseUri" class="java.net.URI">
<constructor-arg value="http://localhost:8080/data"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true"/>
<property name="database" value="HSQL"/>
</bean>
</property>
<property name="persistenceUnitName" value="jpa.sample"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<jdbc:embedded-database id="dataSource" type="HSQL"/>
</beans>
##### META-INF/spring-data-rest/repositories-export.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<import resource="shared.xml"/>
<jpa:repositories base-package="org.springframework.data.rest.test.mvc"/>
</beans>

View File

@@ -204,10 +204,6 @@ public class RepositoryRestController implements InitializingBean {
URI relativeUri = baseUri.relativize(request.getURI());
final Stack<URI> uris = UriUtils.explode(baseUri, relativeUri);
if (LOG.isDebugEnabled()) {
LOG.debug("uris: " + uris);
}
final int uriCnt = uris.size();
if (uris.size() > 0) {
final String repoName = uris.get(0).getPath();
@@ -448,6 +444,11 @@ public class RepositoryRestController implements InitializingBean {
repo.findOne(serId) :
entityMetadata.targetType().newInstance();
if (null == entity) {
model.addAttribute(STATUS, HttpStatus.NOT_FOUND);
return;
}
entityMetadata.doWithEmbedded(new Handler<Attribute, Void>() {
@Override public Void handle(Attribute attribute) {
String name = attribute.getName();

View File

@@ -14,6 +14,7 @@ import org.springframework.mock.web.MockHttpServletRequest
import org.springframework.test.context.ContextConfiguration
import org.springframework.transaction.annotation.Transactional
import org.springframework.ui.ExtendedModelMap
import org.springframework.ui.Model
import spock.lang.Shared
import spock.lang.Specification
@@ -30,21 +31,47 @@ class RepositoryRestControllerSpec extends Specification {
@Autowired
RepositoryRestController controller
ServletServerHttpRequest createRequest(String method, String path) {
return new ServletServerHttpRequest(new MockHttpServletRequest(
MockHttpServletRequest createRequest(String method, String path) {
return new MockHttpServletRequest(
serverPort: 8080,
requestURI: "/data/$path",
method: method
))
)
}
Map GET(String path) {
Model GET(String path) {
def request = createRequest("GET", path)
def model = new ExtendedModelMap()
controller.get(request, model)
controller.get(new ServletServerHttpRequest(request), model)
return model
}
Model POST(String path, m) {
def request = createRequest("POST", path)
request.contentType = "application/json"
request.setContent(mapper.writeValueAsBytes(m))
def model = new ExtendedModelMap()
controller.createOrUpdate(new ServletServerHttpRequest(request), model)
return model
}
Model PUT(String path, m) {
def request = createRequest("PUT", path)
request.contentType = "application/json"
request.setContent(mapper.writeValueAsBytes(m))
def model = new ExtendedModelMap()
controller.createOrUpdate(new ServletServerHttpRequest(request), model)
return model
}
Model DELETE(String path) {
def request = createRequest("DELETE", path)
def model = new ExtendedModelMap()
controller.delete(new ServletServerHttpRequest(request), model)
return model
}
def setupSpec() {
def customSerializerFactory = new CustomSerializerFactory()
customSerializerFactory.addSpecificMapping(SimpleLink, new FluentBeanSerializer(SimpleLink))
@@ -74,15 +101,86 @@ class RepositoryRestControllerSpec extends Specification {
def person = GET("person/1")
then:
person?.resource.name == "John Doe"
person?.resource?.name == "John Doe"
when:
def profiles = GET("person/1/profiles")
def profilesLinks = profiles?.resource.profiles
def profilesLinks = profiles.resource?.profiles
then:
profilesLinks.size() == 2
}
@Transactional
def "responds to POST with ID"() {
when:
def created = POST("person/3", [name: "James Doe"])
then:
created.status == HttpStatus.CREATED
}
@Transactional
def "responds to PUT"() {
given:
POST("person/3", [name: "James Doe"])
when:
def updated = PUT("person/3", [name: "James Doe Jr."])
def getUpdated = GET("person/3")
then:
updated.status == HttpStatus.NO_CONTENT
getUpdated.status == HttpStatus.OK
getUpdated.resource?.name == "James Doe Jr."
}
@Transactional
def "updates links"() {
given:
POST("person/3", [name: "James Doe"])
when:
def link = POST("person/3/addresses", [[href: "$baseUri/address/1".toString()]])
def getUpdated = GET("person/3/addresses")
then:
link.status == HttpStatus.CREATED
getUpdated.status == HttpStatus.OK
getUpdated.resource?.size() == 1
}
@Transactional
def "responds to DELETE"() {
given:
POST("person/3", [name: "James Doe"])
POST("person/3/addresses", [[href: "$baseUri/address/1".toString()]])
when:
def deleted = DELETE("person/3/addresses/1")
def getUpdated = GET("person/3/addresses")
then:
deleted.status == HttpStatus.NO_CONTENT
getUpdated.status == HttpStatus.OK
getUpdated.resource?._links?.size() == 0
when:
def delEntity = DELETE("person/3")
def getUpdEntity = GET("person/3")
then:
delEntity.status == HttpStatus.NO_CONTENT
getUpdEntity.status == HttpStatus.NOT_FOUND
}
}