Updated ResourceProcessor framework to call configured RPs at the appropriate time.
This commit is contained in:
38
build.gradle
38
build.gradle
@@ -10,7 +10,7 @@ ext {
|
||||
|
||||
// Spring
|
||||
springVersion = "3.1.3.RELEASE"
|
||||
//springVersion = "3.2.0.RELEASE"
|
||||
spring32Version = "3.2.1.RELEASE"
|
||||
hateoasVersion = "0.4.0.BUILD-SNAPSHOT"
|
||||
springPluginVersion = "0.8.0.BUILD-SNAPSHOT"
|
||||
springSecurityVersion = "3.1.3.RELEASE"
|
||||
@@ -76,13 +76,22 @@ configure(allprojects) {
|
||||
compile "org.slf4j:slf4j-api:$slf4jVersion"
|
||||
runtime "org.slf4j:jcl-over-slf4j:$slf4jVersion"
|
||||
|
||||
// Spring
|
||||
compile("org.springframework:spring-aop:$springVersion") { force = true }
|
||||
compile("org.springframework:spring-beans:$springVersion") { force = true }
|
||||
compile("org.springframework:spring-context:$springVersion") { force = true }
|
||||
compile("org.springframework:spring-core:$springVersion") { force = true }
|
||||
compile("org.springframework:spring-expression:$springVersion") { force = true }
|
||||
compile("org.springframework:spring-web:$springVersion") { force = true }
|
||||
runtime "cglib:cglib-nodep:$cglibVersion"
|
||||
|
||||
// Testing
|
||||
testCompile "junit:junit-dep:$junitVersion"
|
||||
testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
|
||||
testCompile "org.jmock:jmock-junit4:$jmockVersion"
|
||||
testCompile "org.jmock:jmock-legacy:$jmockVersion"
|
||||
testCompile "org.springframework:spring-test:$springVersion"
|
||||
testRuntime "org.springframework:spring-context-support:$springVersion"
|
||||
testCompile("org.springframework:spring-test:$springVersion") { force = true }
|
||||
testRuntime("org.springframework:spring-context-support:$springVersion") { force = true }
|
||||
testRuntime "ch.qos.logback:logback-classic:$logbackVersion"
|
||||
}
|
||||
}
|
||||
@@ -124,11 +133,6 @@ project("spring-data-rest-core") {
|
||||
// Google Guava
|
||||
compile "com.google.guava:guava:$guavaVersion"
|
||||
|
||||
// Spring
|
||||
compile("org.springframework:spring-core:$springVersion") { force = true }
|
||||
compile("org.springframework:spring-web:$springVersion") { force = true }
|
||||
runtime "cglib:cglib-nodep:$cglibVersion"
|
||||
|
||||
// Spring HATEOAS
|
||||
compile("org.springframework.hateoas:spring-hateoas:$hateoasVersion") {
|
||||
exclude module: "spring-webmvc"
|
||||
@@ -205,6 +209,20 @@ project("spring-data-rest-webmvc") {
|
||||
testCompile "org.eclipse.jetty:jetty-servlet:$jettyVersion"
|
||||
testCompile "org.eclipse.jetty:jetty-webapp:$jettyVersion"
|
||||
testCompile "org.mozilla:rhino:1.7R4"
|
||||
// Spring Data
|
||||
testCompile "org.springframework.data:spring-data-jpa:$sdJpaVersion"
|
||||
testCompile "org.springframework.data:spring-data-mongodb:$sdMongoVersion"
|
||||
testCompile "org.springframework.data:spring-data-gemfire:$sdGemfireVersion"
|
||||
// JODA
|
||||
testCompile "joda-time:joda-time:$jodaVersion"
|
||||
// Jackson
|
||||
testCompile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jacksonVersion"
|
||||
testCompile "com.fasterxml.jackson.datatype:jackson-datatype-hibernate4:$jacksonVersion"
|
||||
// Hibernate
|
||||
testRuntime "org.hibernate:hibernate-entitymanager:$hibernateVersion"
|
||||
testRuntime "org.hibernate:hibernate-validator:$hibernateValidatorVersion"
|
||||
// HSQL
|
||||
testRuntime "org.hsqldb:hsqldb:2.2.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,8 +245,8 @@ project("spring-data-rest-example") {
|
||||
compile "org.springframework.data:spring-data-gemfire:$sdGemfireVersion"
|
||||
|
||||
// Spring Security
|
||||
compile "org.springframework.security:spring-security-config:$springSecurityVersion"
|
||||
compile "org.springframework.security:spring-security-web:$springSecurityVersion"
|
||||
//compile "org.springframework.security:spring-security-config:$springSecurityVersion"
|
||||
//compile "org.springframework.security:spring-security-web:$springSecurityVersion"
|
||||
|
||||
// JODA
|
||||
compile "joda-time:joda-time:$jodaVersion"
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package org.springframework.data.rest.example;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.data.rest.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.example.jpa.Person;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.ResourceProcessor;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
@@ -23,13 +27,17 @@ public class RestExporterExampleRestConfig extends RepositoryRestMvcConfiguratio
|
||||
.setPath("siblings");
|
||||
}
|
||||
|
||||
// @Bean public ResourceProcessor<Resource<?>> globalResourceProcessor() {
|
||||
// return new ResourceProcessor<Resource<?>>() {
|
||||
// @Override public Resource<?> process(Resource<?> resource) {
|
||||
// resource.add(new Link("href", "rel"));
|
||||
// return resource;
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
@Bean public ResourceProcessor<Resource<Person>> personResourceProcessor() {
|
||||
return new ResourceProcessor<Resource<Person>>() {
|
||||
RepositoryRestConfiguration config = config();
|
||||
|
||||
@Override public Resource<Person> process(Resource<Person> resource) {
|
||||
System.out.println("processing " + resource);
|
||||
System.out.println("url: " + config.getBaseUri().toString());
|
||||
resource.add(new Link("http://host:port/path", "myrel"));
|
||||
return resource;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,12 +29,12 @@ public class RestExporterWebInitializer implements WebApplicationInitializer {
|
||||
);
|
||||
|
||||
servletContext.addListener(new ContextLoaderListener(rootCtx));
|
||||
servletContext.addFilter("springSecurity", DelegatingFilterProxy.class);
|
||||
servletContext.getFilterRegistration("springSecurity").addMappingForUrlPatterns(
|
||||
EnumSet.of(DispatcherType.REQUEST),
|
||||
false,
|
||||
"/*"
|
||||
);
|
||||
// servletContext.addFilter("springSecurity", DelegatingFilterProxy.class);
|
||||
// servletContext.getFilterRegistration("springSecurity").addMappingForUrlPatterns(
|
||||
// EnumSet.of(DispatcherType.REQUEST),
|
||||
// false,
|
||||
// "/*"
|
||||
// );
|
||||
|
||||
AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
|
||||
webCtx.register(RestExporterExampleRestConfig.class);
|
||||
|
||||
@@ -42,7 +42,8 @@ public class BaseUriAwareResource<T> extends Resource<T> {
|
||||
String baseUriStr = baseUri.toString();
|
||||
List<Link> links = new ArrayList<Link>();
|
||||
for(Link l : super.getLinks()) {
|
||||
if(!l.getHref().startsWith(baseUriStr)) {
|
||||
if(!l.getHref().startsWith(baseUriStr)
|
||||
&& !l.getHref().startsWith("http")) {
|
||||
links.add(new Link(buildUri(baseUri, l.getHref()).toString(), l.getRel()));
|
||||
} else {
|
||||
links.add(l);
|
||||
@@ -56,7 +57,8 @@ public class BaseUriAwareResource<T> extends Resource<T> {
|
||||
if(null == l) {
|
||||
return null;
|
||||
}
|
||||
if(!l.getHref().startsWith(baseUri.toString())) {
|
||||
if(!l.getHref().startsWith(baseUri.toString())
|
||||
&& !l.getHref().startsWith("http")) {
|
||||
return new Link(buildUri(baseUri, l.getHref()).toString(), l.getRel());
|
||||
} else {
|
||||
return l;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.springframework.data.rest.repository.context;
|
||||
|
||||
import static org.springframework.util.ClassUtils.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.data.rest.repository.PersistentEntityResource;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.ResourceProcessor;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public class PersistentEntityResourceProcessor implements ResourceProcessor<PersistentEntityResource<?>> {
|
||||
|
||||
private final List<DomainTypeResourceProcessor> resourceProcessors = new ArrayList<DomainTypeResourceProcessor>();
|
||||
|
||||
@Autowired
|
||||
public PersistentEntityResourceProcessor(Repositories repositories,
|
||||
List<ResourceProcessor<Resource<?>>> resourceProcessors) {
|
||||
if(null != resourceProcessors) {
|
||||
for(ResourceProcessor<Resource<?>> rp : resourceProcessors) {
|
||||
TypeInformation<?> typeInfo = ClassTypeInformation.from(rp.getClass());
|
||||
TypeInformation<?> domainType = typeInfo.getTypeArguments().get(0);
|
||||
if(null != repositories.getPersistentEntity(domainType.getType())) {
|
||||
this.resourceProcessors.add(new DomainTypeResourceProcessor(domainType.getType(), rp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public PersistentEntityResource<?> process(PersistentEntityResource<?> resource) {
|
||||
Object content = resource.getContent();
|
||||
if(null == content) {
|
||||
return resource;
|
||||
}
|
||||
|
||||
Class<?> domainType = content.getClass();
|
||||
for(DomainTypeResourceProcessor rp : resourceProcessors) {
|
||||
if(isAssignable(domainType, rp.domainType)) {
|
||||
rp.resourceProcessor.process(resource);
|
||||
}
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
private static class DomainTypeResourceProcessor {
|
||||
final Class<?> domainType;
|
||||
final ResourceProcessor<Resource<?>> resourceProcessor;
|
||||
|
||||
private DomainTypeResourceProcessor(Class<?> domainType, ResourceProcessor<Resource<?>> resourceProcessor) {
|
||||
this.domainType = domainType;
|
||||
this.resourceProcessor = resourceProcessor;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,13 @@ public class BaseUriMethodArgumentResolver implements HandlerMethodArgumentResol
|
||||
@Autowired
|
||||
private RepositoryRestConfiguration config;
|
||||
|
||||
public BaseUriMethodArgumentResolver() {
|
||||
}
|
||||
|
||||
public BaseUriMethodArgumentResolver(RepositoryRestConfiguration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override public boolean supportsParameter(MethodParameter parameter) {
|
||||
return (null != parameter.getParameterAnnotation(BaseURI.class)
|
||||
&& parameter.getParameterType() == URI.class);
|
||||
|
||||
@@ -31,6 +31,13 @@ public class PagingAndSortingMethodArgumentResolver implements HandlerMethodArgu
|
||||
@Autowired
|
||||
private RepositoryRestConfiguration config;
|
||||
|
||||
public PagingAndSortingMethodArgumentResolver() {
|
||||
}
|
||||
|
||||
public PagingAndSortingMethodArgumentResolver(RepositoryRestConfiguration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override public boolean supportsParameter(MethodParameter parameter) {
|
||||
return ClassUtils.isAssignable(parameter.getParameterType(), PagingAndSorting.class);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package org.springframework.data.rest.webmvc;
|
||||
|
||||
import static org.springframework.data.util.ClassTypeInformation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.rest.webmvc.support.JsonpResponse;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.ResourceProcessor;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public class PersistentEntityResourceProcessorReturnValueHandler implements HandlerMethodReturnValueHandler {
|
||||
|
||||
private final HandlerMethodReturnValueHandler delegate;
|
||||
private final List<Wrapper> processors = new ArrayList<Wrapper>();
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public PersistentEntityResourceProcessorReturnValueHandler(HandlerMethodReturnValueHandler delegate,
|
||||
List<ResourceProcessor<?>> processors) {
|
||||
this.delegate = delegate;
|
||||
for(ResourceProcessor<?> rp : processors) {
|
||||
TypeInformation<?> componentType = from(rp.getClass())
|
||||
.getSuperTypeInformation(ResourceProcessor.class)
|
||||
.getComponentType();
|
||||
if(Resources.class.isAssignableFrom(componentType.getType())) {
|
||||
this.processors.add(new ResourcesProcessorWrapper(componentType.getComponentType().getType(),
|
||||
(ResourceProcessor<Resources<?>>)rp));
|
||||
} else if(Resource.class.isAssignableFrom(componentType.getType())) {
|
||||
this.processors.add(new ResourceProcessorWrapper(componentType.getComponentType().getType(),
|
||||
(ResourceProcessor<Resource<?>>)rp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean supportsReturnType(MethodParameter returnType) {
|
||||
Class<?> controller = returnType.getMethod().getDeclaringClass();
|
||||
return RepositoryController.class.isAssignableFrom(controller)
|
||||
|| RepositoryEntityController.class.isAssignableFrom(controller)
|
||||
|| RepositoryPropertyReferenceController.class.isAssignableFrom(controller)
|
||||
|| RepositorySearchController.class.isAssignableFrom(controller);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
@Override
|
||||
public void handleReturnValue(Object returnValue,
|
||||
MethodParameter methodParam,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest nativeRequest) throws Exception {
|
||||
Class<?> returnValueType = returnValue.getClass();
|
||||
Class<?> entityType = null;
|
||||
|
||||
if(JsonpResponse.class.isAssignableFrom(returnValueType)) {
|
||||
entityType = ((JsonpResponse)returnValue).getResponseEntity().getBody().getClass();
|
||||
} else if(ResponseEntity.class.isAssignableFrom(returnValueType)) {
|
||||
entityType = ((ResponseEntity)returnValue).getBody().getClass();
|
||||
} else if(Resources.class.isAssignableFrom(returnValueType)) {
|
||||
Collection c = ((Resources)returnValue).getContent();
|
||||
Object o;
|
||||
if(null != c && !c.isEmpty() && null != (o = c.iterator().next())) {
|
||||
entityType = o.getClass();
|
||||
} else {
|
||||
if(delegate.supportsReturnType(methodParam)) {
|
||||
delegate.handleReturnValue(returnValue,
|
||||
methodParam,
|
||||
mavContainer,
|
||||
nativeRequest);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if(Resource.class.isAssignableFrom(returnValueType)) {
|
||||
entityType = ((Resource)returnValue).getContent().getClass();
|
||||
}
|
||||
|
||||
for(Wrapper w : processors) {
|
||||
if(w.type.isAssignableFrom(entityType)) {
|
||||
if(ResourcesProcessorWrapper.class.isAssignableFrom(w.getClass())
|
||||
&& Resources.class.isAssignableFrom(returnValueType)) {
|
||||
((ResourcesProcessorWrapper)w).processor.process((Resources<?>)returnValue);
|
||||
} else if(ResourceProcessorWrapper.class.isAssignableFrom(w.getClass())
|
||||
&& Resource.class.isAssignableFrom(returnValueType)) {
|
||||
((ResourceProcessorWrapper)w).processor.process((Resource<?>)returnValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(delegate.supportsReturnType(methodParam)) {
|
||||
delegate.handleReturnValue(returnValue,
|
||||
methodParam,
|
||||
mavContainer,
|
||||
nativeRequest);
|
||||
}
|
||||
}
|
||||
|
||||
static class Wrapper {
|
||||
Class<?> type;
|
||||
TypeInformation<?> typeInfo;
|
||||
|
||||
Wrapper(Class<?> type) {
|
||||
this.type = type;
|
||||
this.typeInfo = from(type);
|
||||
}
|
||||
}
|
||||
|
||||
static class ResourcesProcessorWrapper extends Wrapper {
|
||||
ResourceProcessor<Resources<?>> processor;
|
||||
|
||||
ResourcesProcessorWrapper(Class<?> type, ResourceProcessor<Resources<?>> processor) {
|
||||
super(type);
|
||||
this.processor = processor;
|
||||
}
|
||||
}
|
||||
|
||||
static class ResourceProcessorWrapper extends Wrapper {
|
||||
ResourceProcessor<Resource<?>> processor;
|
||||
|
||||
ResourceProcessorWrapper(Class<?> type, ResourceProcessor<Resource<?>> processor) {
|
||||
super(type);
|
||||
this.processor = processor;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,60 +30,64 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
||||
|
||||
/**
|
||||
* Special {@link RequestMappingHandlerAdapter} that tweaks the {@link HandlerMethodReturnValueHandlerComposite} to be
|
||||
* proxied by a {@link ResourceProcessorHandlerMethodReturnValueHandler} which will invoke the {@link ResourceProcessor}s
|
||||
* proxied by a {@link ResourceProcessorHandlerMethodReturnValueHandler} which will invoke the {@link
|
||||
* ResourceProcessor}s
|
||||
* found in the application context and eventually delegate to the originally configured
|
||||
* {@link HandlerMethodReturnValueHandler}.
|
||||
* <p>
|
||||
* This is a separate component as it might make sense to deploy it in a standalone SpringMVC application to enable post
|
||||
* <p/>
|
||||
* This is a separate component as it might make sense to deploy it in a standalone SpringMVC application to enable
|
||||
* post
|
||||
* processing. It would actually make most sense in Spring HATEOAS project.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ResourceProcessorInvokingHandlerAdapter extends RequestMappingHandlerAdapter {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<ResourceProcessor<?>> resourcesProcessors = new ArrayList<ResourceProcessor<?>>();
|
||||
@Autowired(required = false)
|
||||
private List<ResourceProcessor<?>> resourcesProcessors = new ArrayList<ResourceProcessor<?>>();
|
||||
|
||||
/**
|
||||
* Empty constructor to setup a {@link ResourceProcessorInvokingHandlerAdapter}.
|
||||
*/
|
||||
public ResourceProcessorInvokingHandlerAdapter() {
|
||||
/**
|
||||
* Empty constructor to setup a {@link ResourceProcessorInvokingHandlerAdapter}.
|
||||
*/
|
||||
public ResourceProcessorInvokingHandlerAdapter() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor to copy configuration of {@link HttpMessageConverter}s, {@link WebBindingInitializer}, custom
|
||||
* {@link HandlerMethodArgumentResolver}s and custom {@link HandlerMethodReturnValueHandler}s.
|
||||
*
|
||||
* @param original must not be {@literal null}.
|
||||
*/
|
||||
public ResourceProcessorInvokingHandlerAdapter(RequestMappingHandlerAdapter original) {
|
||||
|
||||
Assert.notNull(original);
|
||||
/**
|
||||
* Copy constructor to copy configuration of {@link HttpMessageConverter}s, {@link WebBindingInitializer}, custom
|
||||
* {@link HandlerMethodArgumentResolver}s and custom {@link HandlerMethodReturnValueHandler}s.
|
||||
*
|
||||
* @param original
|
||||
* must not be {@literal null}.
|
||||
*/
|
||||
public ResourceProcessorInvokingHandlerAdapter(RequestMappingHandlerAdapter original) {
|
||||
|
||||
setMessageConverters(original.getMessageConverters());
|
||||
setWebBindingInitializer(original.getWebBindingInitializer());
|
||||
setCustomArgumentResolvers(original.getCustomArgumentResolvers());
|
||||
setCustomReturnValueHandlers(original.getCustomReturnValueHandlers());
|
||||
}
|
||||
Assert.notNull(original);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
setMessageConverters(original.getMessageConverters());
|
||||
setWebBindingInitializer(original.getWebBindingInitializer());
|
||||
setCustomArgumentResolvers(original.getCustomArgumentResolvers());
|
||||
setCustomReturnValueHandlers(original.getCustomReturnValueHandlers());
|
||||
}
|
||||
|
||||
super.afterPropertiesSet();
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
// Retrieve actual handlers to use as delegate
|
||||
HandlerMethodReturnValueHandlerComposite oldHandlers = getReturnValueHandlers();
|
||||
super.afterPropertiesSet();
|
||||
|
||||
// Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones
|
||||
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
|
||||
newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, resourcesProcessors));
|
||||
// Retrieve actual handlers to use as delegate
|
||||
HandlerMethodReturnValueHandlerComposite oldHandlers = getReturnValueHandlers();
|
||||
|
||||
// Configure the new handler to be used
|
||||
this.setReturnValueHandlers(newHandlers);
|
||||
}
|
||||
// Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones
|
||||
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
|
||||
newHandlers.add(new PersistentEntityResourceProcessorReturnValueHandler(oldHandlers, resourcesProcessors));
|
||||
newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, resourcesProcessors));
|
||||
|
||||
// Configure the new handler to be used
|
||||
this.setReturnValueHandlers(newHandlers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.data.rest.webmvc;
|
||||
|
||||
import org.jmock.integration.junit4.JMock;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.jmock.lib.legacy.ClassImposteriser;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Abstract base classes for JUnit tests that use JMock.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@RunWith(JMock.class)
|
||||
public abstract class AbstractJMockTests {
|
||||
|
||||
protected JUnit4Mockery context = new JUnit4Mockery() {{
|
||||
setImposteriser(ClassImposteriser.INSTANCE);
|
||||
}};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.springframework.data.rest.webmvc;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.rest.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.webmvc.annotation.BaseURI;
|
||||
import org.springframework.data.rest.webmvc.support.PagingAndSorting;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public class CustomMethodArgumentResolverTests extends AbstractJMockTests {
|
||||
|
||||
static final MethodParameter BASE_URI;
|
||||
static final MethodParameter PAGE_SORT;
|
||||
|
||||
static {
|
||||
try {
|
||||
BASE_URI = MethodParameter.forMethodOrConstructor(
|
||||
Methods.class.getDeclaredMethod("baseUri", URI.class),
|
||||
0
|
||||
);
|
||||
PAGE_SORT = MethodParameter.forMethodOrConstructor(
|
||||
Methods.class.getDeclaredMethod("pagingAndSorting", PagingAndSorting.class),
|
||||
0
|
||||
);
|
||||
} catch(NoSuchMethodException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final RepositoryRestConfiguration config =
|
||||
new RepositoryRestConfiguration()
|
||||
.setBaseUri(URI.create("http://localhost:8080"));
|
||||
private final BaseUriMethodArgumentResolver baseUriResolver =
|
||||
new BaseUriMethodArgumentResolver(config);
|
||||
private final PagingAndSortingMethodArgumentResolver pageSortResolver =
|
||||
new PagingAndSortingMethodArgumentResolver(config);
|
||||
private ModelAndViewContainer mavContainer;
|
||||
private WebDataBinderFactory webDataBinderFactory;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mavContainer = new ModelAndViewContainer();
|
||||
webDataBinderFactory = context.mock(WebDataBinderFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void baseUriMethodArgumentResolver() throws Exception {
|
||||
assertThat("Finds @BaseURI-annotated java.net.URI parameter",
|
||||
baseUriResolver.supportsParameter(BASE_URI),
|
||||
is(true));
|
||||
|
||||
// Resolve the base URI
|
||||
URI baseUri = (URI)baseUriResolver.resolveArgument(
|
||||
BASE_URI,
|
||||
mavContainer,
|
||||
new ServletWebRequest(Requests.ROOT_REQUEST),
|
||||
webDataBinderFactory
|
||||
);
|
||||
|
||||
assertThat("Base URI should be 'http://localhost:8080'",
|
||||
baseUri.toString(),
|
||||
is("http://localhost:8080"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pagingAndSortingMethodArgumentResolver() throws Exception {
|
||||
assertThat("Finds PagingAndSorting parameter",
|
||||
pageSortResolver.supportsParameter(PAGE_SORT),
|
||||
is(true));
|
||||
|
||||
// Resolve Page and Sort information
|
||||
PagingAndSorting pageSort = (PagingAndSorting)pageSortResolver.resolveArgument(
|
||||
PAGE_SORT,
|
||||
mavContainer,
|
||||
new ServletWebRequest(Requests.PAGE_REQUEST),
|
||||
webDataBinderFactory
|
||||
);
|
||||
|
||||
assertThat("Finds page parameter value",
|
||||
pageSort.getPageNumber(),
|
||||
is(1));
|
||||
assertThat("Finds limit parameter value",
|
||||
pageSort.getPageSize(),
|
||||
is(5));
|
||||
}
|
||||
|
||||
static class Methods {
|
||||
void baseUri(@BaseURI URI baseUri) {
|
||||
}
|
||||
|
||||
void pagingAndSorting(PagingAndSorting pageSort) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.data.rest.webmvc;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||
import org.springframework.data.rest.webmvc.gemfire.GemfireRepositoryConfig;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.data.rest.webmvc.mongodb.MongoDbRepositoryConfig;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@Configuration
|
||||
@Import({
|
||||
JpaRepositoryConfig.class,
|
||||
MongoDbRepositoryConfig.class,
|
||||
GemfireRepositoryConfig.class
|
||||
})
|
||||
public class RepositoryRestMvcTestConfig extends RepositoryRestMvcConfiguration {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.springframework.data.rest.webmvc;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public abstract class Requests {
|
||||
|
||||
public static MockHttpServletRequest ROOT_REQUEST = new MockHttpServletRequest("GET", "http://localhost:8080/");
|
||||
public static MockHttpServletRequest PAGE_REQUEST = new MockHttpServletRequest("GET", "http://localhost:8080/");
|
||||
|
||||
static {
|
||||
PAGE_REQUEST.setParameter("page", "2");
|
||||
PAGE_REQUEST.setParameter("limit", "5");
|
||||
}
|
||||
|
||||
private Requests() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
|
||||
|
||||
/**
|
||||
* Spring JavaConfig configuration class to setup a Spring container and infrastructure components.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
*/
|
||||
@Configuration
|
||||
@ImportResource("classpath:META-INF/spring/cache-config.xml")
|
||||
@EnableGemfireRepositories
|
||||
public class GemfireRepositoryConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.core;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
* Base class for persistent classes.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
*/
|
||||
public class AbstractPersistentEntity {
|
||||
|
||||
@Id
|
||||
private final Long id;
|
||||
|
||||
/**
|
||||
* Returns the identifier of the entity.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
protected AbstractPersistentEntity(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
protected AbstractPersistentEntity() {
|
||||
this.id = null;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.id == null || obj == null || !(this.getClass().equals(obj.getClass()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AbstractPersistentEntity that = (AbstractPersistentEntity) obj;
|
||||
|
||||
return this.id.equals(that.getId());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id == null ? 0 : id.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.core;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An address.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Address {
|
||||
|
||||
private final String street, city, country;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Address} from the given street, city and country.
|
||||
*
|
||||
* @param street must not be {@literal null} or empty.
|
||||
* @param city must not be {@literal null} or empty.
|
||||
* @param country must not be {@literal null} or empty.
|
||||
*/
|
||||
public Address(String street, String city, String country) {
|
||||
|
||||
Assert.hasText(street, "Street must not be null or empty!");
|
||||
Assert.hasText(city, "City must not be null or empty!");
|
||||
Assert.hasText(country, "Country must not be null or empty!");
|
||||
|
||||
this.street = street;
|
||||
this.city = city;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the current {@link Address} instance which is a new entity in terms of persistence.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Address getCopy() {
|
||||
return new Address(this.street, this.city, this.country);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the street.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the city.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the country.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.core;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.gemfire.mapping.Region;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* A customer.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
*/
|
||||
@Region
|
||||
public class Customer extends AbstractPersistentEntity {
|
||||
private EmailAddress emailAddress;
|
||||
private String firstname, lastname;
|
||||
private Set<Address> addresses = new HashSet<Address>();
|
||||
|
||||
/**
|
||||
* Creates a new {@link Customer} from the given parameters.
|
||||
*
|
||||
* @param id
|
||||
* the unique id;
|
||||
* @param emailAddress
|
||||
* must not be {@literal null} or empty.
|
||||
* @param firstname
|
||||
* must not be {@literal null} or empty.
|
||||
* @param lastname
|
||||
* must not be {@literal null} or empty.
|
||||
*/
|
||||
public Customer(Long id, EmailAddress emailAddress, String firstname, String lastname) {
|
||||
super(id);
|
||||
Assert.hasText(firstname);
|
||||
Assert.hasText(lastname);
|
||||
Assert.notNull(emailAddress);
|
||||
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
protected Customer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given {@link Address} to the {@link Customer}.
|
||||
*
|
||||
* @param address
|
||||
* must not be {@literal null}.
|
||||
*/
|
||||
public void add(Address address) {
|
||||
|
||||
Assert.notNull(address);
|
||||
this.addresses.add(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the firstname of the {@link Customer}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the firstname of the {@link Customer}.
|
||||
*
|
||||
* @param firstname
|
||||
*/
|
||||
public void setFirstname(String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lastname of the {@link Customer}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lastname of the {@link Customer}.
|
||||
*
|
||||
* @param lastname
|
||||
*/
|
||||
public void setLastname(String lastname) {
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link EmailAddress} of the {@link Customer}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public EmailAddress getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the emailAddress of the {@link Customer}.
|
||||
*
|
||||
* @param emailAddress
|
||||
*/
|
||||
public void setEmailAddress(EmailAddress emailAddress) {
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link Customer}'s addresses.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<Address> getAddresses() {
|
||||
return Collections.unmodifiableSet(addresses);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
/**
|
||||
* Repository interface to access {@link Customer}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
*/
|
||||
|
||||
public interface CustomerRepository extends CrudRepository<Customer, Long> {
|
||||
|
||||
/**
|
||||
* Finds all {@link Customer}s with the given lastname.
|
||||
*
|
||||
* @param lastname
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Customer> findByLastname(@Param("lastname") String lastname);
|
||||
|
||||
/**
|
||||
* Finds the Customer with the given {@link EmailAddress}.
|
||||
*
|
||||
* @param emailAddress
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Customer findByEmailAddress(@Param("email") EmailAddress emailAddress);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.core;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Value object to represent email addresses.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
public final class EmailAddress {
|
||||
|
||||
private static final String EMAIL_REGEX = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
|
||||
private static final Pattern PATTERN = Pattern.compile(EMAIL_REGEX);
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Creates a new {@link EmailAddress} from the given {@link String} representation.
|
||||
*
|
||||
* @param emailAddress
|
||||
* must not be {@literal null} or empty.
|
||||
*/
|
||||
@JsonCreator
|
||||
public EmailAddress(String emailAddress) {
|
||||
Assert.isTrue(isValid(emailAddress), "Invalid email address!");
|
||||
this.value = emailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link String} is a valid {@link EmailAddress} which means you can safely instantiate
|
||||
* the
|
||||
* class.
|
||||
*
|
||||
* @param candidate
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValid(String candidate) {
|
||||
return candidate == null ? false : PATTERN.matcher(candidate).matches();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if(this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!(obj instanceof EmailAddress)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EmailAddress that = (EmailAddress)obj;
|
||||
return this.value.equals(that.value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
@Component
|
||||
static class EmailAddressToStringConverter implements Converter<EmailAddress, String> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public String convert(EmailAddress source) {
|
||||
return source == null ? null : source.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
static class StringToEmailAddressConverter implements Converter<String, EmailAddress> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
public EmailAddress convert(String source) {
|
||||
return StringUtils.hasText(source) ? new EmailAddress(source) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.core;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.gemfire.mapping.Region;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* A product.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
*/
|
||||
@Region
|
||||
public class Product extends AbstractPersistentEntity {
|
||||
|
||||
private String name, description;
|
||||
private BigDecimal price;
|
||||
private Map<String, String> attributes = new HashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Creates a new {@link Product} with the given name.
|
||||
*
|
||||
* @param id
|
||||
* a unique Id
|
||||
* @param name
|
||||
* must not be {@literal null} or empty.
|
||||
* @param price
|
||||
* must not be {@literal null} or less than or equal to zero.
|
||||
*/
|
||||
public Product(Long id, String name, BigDecimal price) {
|
||||
this(id, name, price, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Product} from the given name and description.
|
||||
*
|
||||
* @param id
|
||||
* a unique Id
|
||||
* @param name
|
||||
* must not be {@literal null} or empty.
|
||||
* @param price
|
||||
* must not be {@literal null} or less than or equal to zero.
|
||||
* @param description
|
||||
*/
|
||||
@PersistenceConstructor
|
||||
public Product(Long id, String name, BigDecimal price, String description) {
|
||||
super(id);
|
||||
Assert.hasText(name, "Name must not be null or empty!");
|
||||
Assert.isTrue(BigDecimal.ZERO.compareTo(price) < 0, "Price must be greater than zero!");
|
||||
|
||||
this.name = name;
|
||||
this.price = price;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
protected Product() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute with the given name to the given value.
|
||||
*
|
||||
* @param name
|
||||
* must not be {@literal null} or empty.
|
||||
* @param value
|
||||
*/
|
||||
public void setAttribute(String name, String value) {
|
||||
|
||||
Assert.hasText(name);
|
||||
|
||||
if(value == null) {
|
||||
this.attributes.remove(value);
|
||||
} else {
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Product}'s name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Product}'s description.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the custom attributes of the {@link Product}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Map<String, String> getAttributes() {
|
||||
return Collections.unmodifiableMap(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the price of the {@link Product}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal getPrice() {
|
||||
return price;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.gemfire.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Repository interface to access {@link Product}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David TuranskiGem
|
||||
*/
|
||||
public interface ProductRepository extends CrudRepository<Product, Long> {
|
||||
|
||||
/**
|
||||
* Returns a list of {@link Product}s having a description which contains the given snippet.
|
||||
* @param the search string
|
||||
* @return
|
||||
*/
|
||||
|
||||
List<Product> findByDescriptionContaining(String description);
|
||||
|
||||
/**
|
||||
* Returns all {@link Product}s having the given attribute value.
|
||||
* @param attribute
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
@Query("SELECT * FROM /Product where attributes[$1] = $2")
|
||||
List<Product> findByAttributes(String key, String value);
|
||||
|
||||
List<Product> findByName(String name);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.order;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.springframework.data.rest.webmvc.gemfire.core.Product;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class LineItem {
|
||||
|
||||
private BigDecimal price;
|
||||
private int amount;
|
||||
private Long productId;
|
||||
|
||||
/**
|
||||
* Creates a new {@link LineItem} for the given {@link Product}.
|
||||
*
|
||||
* @param product
|
||||
* must not be {@literal null}.
|
||||
*/
|
||||
public LineItem(Product product) {
|
||||
this(product, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link LineItem} for the given {@link Product} and amount.
|
||||
*
|
||||
* @param product
|
||||
* must not be {@literal null}.
|
||||
* @param amount
|
||||
*/
|
||||
public LineItem(Product product, int amount) {
|
||||
Assert.notNull(product, "The given Product must not be null!");
|
||||
Assert.isTrue(amount > 0, "The amount of Products to be bought must be greater than 0!");
|
||||
|
||||
this.productId = product.getId();
|
||||
this.amount = amount;
|
||||
this.price = product.getPrice();
|
||||
}
|
||||
|
||||
protected LineItem() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the {@link Product} the {@link LineItem} refers to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Long getProductId() {
|
||||
return productId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of {@link Product}s to be ordered.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the price a single unit of the {@link LineItem}'s product.
|
||||
*
|
||||
* @return the price
|
||||
*/
|
||||
public BigDecimal getUnitPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total for the {@link LineItem}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal getTotal() {
|
||||
return price.multiply(BigDecimal.valueOf(amount));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.order;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.gemfire.mapping.Region;
|
||||
import org.springframework.data.rest.webmvc.gemfire.core.AbstractPersistentEntity;
|
||||
import org.springframework.data.rest.webmvc.gemfire.core.Address;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
*/
|
||||
@Region
|
||||
public class Order extends AbstractPersistentEntity {
|
||||
|
||||
private Long customerId;
|
||||
private Address billingAddress;
|
||||
private Address shippingAddress;
|
||||
private Set<LineItem> lineItems = new HashSet<LineItem>();
|
||||
|
||||
/**
|
||||
* Creates a new {@link Order} for the given {@link org.springframework.data.rest.webmvc.gemfire.core.Customer}.
|
||||
*
|
||||
* @param id
|
||||
* order ID
|
||||
* @param customerId
|
||||
* must not be {@literal null}.
|
||||
* @param shippingAddress
|
||||
* must not be {@literal null}.
|
||||
*/
|
||||
public Order(Long id, Long customerId, Address shippingAddress) {
|
||||
super(id);
|
||||
Assert.notNull(customerId);
|
||||
Assert.notNull(shippingAddress);
|
||||
|
||||
this.customerId = customerId;
|
||||
this.shippingAddress = shippingAddress;
|
||||
}
|
||||
|
||||
protected Order() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given {@link LineItem} to the {@link Order}.
|
||||
*
|
||||
* @param lineItem
|
||||
*/
|
||||
public void add(LineItem lineItem) {
|
||||
this.lineItems.add(lineItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the {@link org.springframework.data.rest.webmvc.gemfire.core.Customer} who placed the {@link
|
||||
* Order}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Long getCustomerId() {
|
||||
return customerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the billing {@link Address} for this order.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Address getBillingAddress() {
|
||||
return billingAddress != null ? billingAddress : shippingAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shipping {@link Address} for this order;
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Address getShippingAddress() {
|
||||
return shippingAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link LineItem}s currently belonging to the {@link Order}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<LineItem> getLineItems() {
|
||||
return Collections.unmodifiableSet(lineItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total of the {@link Order}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal getTotal() {
|
||||
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
|
||||
for(LineItem item : lineItems) {
|
||||
total = total.add(item.getTotal());
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.gemfire.order;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
*/
|
||||
public interface OrderRepository extends CrudRepository<Order, Long> {
|
||||
List<Order> findByCustomerId(Long customerId);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.springframework.data.rest.webmvc.jpa;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.orm.jpa.JpaDialect;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = JpaRepositoryConfig.class)
|
||||
@EnableJpaRepositories
|
||||
@EnableTransactionManagement
|
||||
public class JpaRepositoryConfig {
|
||||
|
||||
@Bean public DataSource dataSource() {
|
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||
return builder.setType(EmbeddedDatabaseType.HSQL).build();
|
||||
}
|
||||
|
||||
@Bean public EntityManagerFactory entityManagerFactory() {
|
||||
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
vendorAdapter.setDatabase(Database.HSQL);
|
||||
vendorAdapter.setGenerateDdl(true);
|
||||
|
||||
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
|
||||
factory.setJpaVendorAdapter(vendorAdapter);
|
||||
factory.setPackagesToScan(getClass().getPackage().getName());
|
||||
factory.setDataSource(dataSource());
|
||||
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
return factory.getObject();
|
||||
}
|
||||
|
||||
@Bean public JpaDialect jpaDialect() {
|
||||
return new HibernateJpaDialect();
|
||||
}
|
||||
|
||||
@Bean public PlatformTransactionManager transactionManager() {
|
||||
JpaTransactionManager txManager = new JpaTransactionManager();
|
||||
txManager.setEntityManagerFactory(entityManagerFactory());
|
||||
return txManager;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.springframework.data.rest.webmvc.jpa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.PrePersist;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.data.rest.repository.annotation.Description;
|
||||
|
||||
/**
|
||||
* An entity that represents a person.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@Entity
|
||||
public class Person {
|
||||
|
||||
private Long id;
|
||||
@Description("A person's first name")
|
||||
private String firstName;
|
||||
@Description("A person's last name")
|
||||
private String lastName;
|
||||
@Description("A person's siblings")
|
||||
private List<Person> siblings = Collections.emptyList();
|
||||
private Person father;
|
||||
@Description("Timestamp this person object was created")
|
||||
private Date created;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
@Id @GeneratedValue public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public Person addSibling(Person p) {
|
||||
if(siblings == Collections.EMPTY_LIST) {
|
||||
siblings = new ArrayList<Person>();
|
||||
}
|
||||
siblings.add(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ManyToMany public List<Person> getSiblings() {
|
||||
return siblings;
|
||||
}
|
||||
|
||||
public void setSiblings(List<Person> siblings) {
|
||||
this.siblings = siblings;
|
||||
}
|
||||
|
||||
@ManyToOne public Person getFather() {
|
||||
return father;
|
||||
}
|
||||
|
||||
public void setFather(Person father) {
|
||||
this.father = father;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
private void prePersist() {
|
||||
this.created = Calendar.getInstance().getTime();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.springframework.data.rest.webmvc.jpa;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@Component
|
||||
public class PersonLoader implements InitializingBean {
|
||||
|
||||
@Autowired
|
||||
PersonRepository people;
|
||||
|
||||
@Override public void afterPropertiesSet() throws Exception {
|
||||
Person billyBob = people.save(new Person("Billy Bob", "Thornton"));
|
||||
|
||||
Person john = new Person("John", "Doe");
|
||||
Person jane = new Person("Jane", "Doe");
|
||||
john.addSibling(jane);
|
||||
john.setFather(billyBob);
|
||||
jane.addSibling(john);
|
||||
jane.setFather(billyBob);
|
||||
|
||||
people.save(Arrays.asList(john, jane));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.springframework.data.rest.webmvc.jpa;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.rest.convert.ISO8601DateConverter;
|
||||
import org.springframework.data.rest.repository.annotation.ConvertWith;
|
||||
import org.springframework.data.rest.repository.annotation.RestResource;
|
||||
|
||||
/**
|
||||
* A repository to manage {@link Person}s.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@RestResource(rel = "people", path = "people")
|
||||
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
|
||||
|
||||
@RestResource(rel = "firstname", path = "firstname")
|
||||
public Page<Person> findByFirstName(@Param("firstName") String firstName, Pageable pageable);
|
||||
|
||||
public Person findFirstPersonByFirstName(@Param("firstName") String firstName);
|
||||
|
||||
public Page<Person> findByCreatedGreaterThan(@Param("date") Date date, Pageable pageable);
|
||||
|
||||
@Query("select p from Person p where p.created > :date")
|
||||
public Page<Person> findByCreatedUsingISO8601Date(@Param("date")
|
||||
@ConvertWith(
|
||||
ISO8601DateConverter.class)
|
||||
Date date,
|
||||
Pageable pageable);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.springframework.data.rest.webmvc.mongodb;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = MongoDbRepositoryConfig.class)
|
||||
@EnableMongoRepositories
|
||||
public class MongoDbRepositoryConfig {
|
||||
|
||||
@Bean public MongoDbFactory mongoDbFactory() throws UnknownHostException {
|
||||
return new SimpleMongoDbFactory(new Mongo("localhost"), "spring-data-rest-example");
|
||||
}
|
||||
|
||||
@Bean public MongoTemplate mongoTemplate() throws UnknownHostException {
|
||||
return new MongoTemplate(mongoDbFactory());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.springframework.data.rest.webmvc.mongodb;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@Document
|
||||
public class Profile {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private Long person;
|
||||
private String type;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Profile setId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getPerson() {
|
||||
return person;
|
||||
}
|
||||
|
||||
public Profile setPerson(Long person) {
|
||||
this.person = person;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Profile setType(String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.springframework.data.rest.webmvc.mongodb;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public interface ProfileRepository extends CrudRepository<Profile, String> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
|
||||
<persistence-unit name="jpa.sample">
|
||||
<properties>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
|
||||
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:spring"/>
|
||||
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
|
||||
<property name="hibernate.connection.username" value="sa"/>
|
||||
<property name="hibernate.connection.password" value=""/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:gfe="http://www.springframework.org/schema/gemfire"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<gfe:cache use-bean-factory-locator="false"/>
|
||||
|
||||
<gfe:replicated-region id="Customer"/>
|
||||
<gfe:replicated-region id="Order"/>
|
||||
<gfe:replicated-region id="Product"/>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user