diff --git a/spring-data-rest-webmvc/pom.xml b/spring-data-rest-webmvc/pom.xml
index 09eba5e7f..ed5652daa 100644
--- a/spring-data-rest-webmvc/pom.xml
+++ b/spring-data-rest-webmvc/pom.xml
@@ -20,6 +20,7 @@
2.0.9
2.0.2.1
4.0.1.RELEASE
+ 2.3.7
@@ -122,6 +123,13 @@
test
+
+ org.codehaus.groovy
+ groovy-all
+ ${groovy.version}
+ test
+
+
@@ -481,6 +489,9 @@
target/generated-sources/annotations
org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
true
+
+ org.springframework.data.rest.webmvc.mongodb.groovy,groovy.lang
+
diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java
index 4d02b0d8e..613bffb2b 100644
--- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java
+++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2015 the original author or authors.
+ * Copyright 2012-2016 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.
@@ -54,6 +54,7 @@ import org.springframework.util.StringUtils;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
/**
@@ -61,6 +62,7 @@ import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
*
* @author Jon Brisbin
* @author Oliver Gierke
+ * @author Greg Turnquist
*/
public class PersistentEntityToJsonSchemaConverter implements ConditionalGenericConverter {
@@ -186,18 +188,25 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
}
}
- TypeInformation> propertyType = persistentProperty == null
- ? ClassTypeInformation.from(definition.getPrimaryMember().getRawType())
+ boolean isPersistentPropertyNull = persistentProperty == null;
+
+ AnnotatedMember primaryMember = definition.getPrimaryMember();
+ if (primaryMember == null) { // Ignore bean definitions with neither a getter nor a setter
+ continue;
+ }
+
+ TypeInformation> propertyType = isPersistentPropertyNull
+ ? ClassTypeInformation.from(primaryMember.getRawType())
: persistentProperty.getTypeInformation();
TypeInformation> actualPropertyType = propertyType.getActualType();
Class> rawPropertyType = propertyType.getType();
JsonSchemaFormat format = configuration.getMetadataConfiguration().getSchemaFormatFor(rawPropertyType);
- ResourceDescription description = persistentProperty == null
+ ResourceDescription description = isPersistentPropertyNull
? jackson.getFallbackDescription(metadata, definition) : getDescriptionFor(persistentProperty, metadata);
JsonSchemaProperty property = getSchemaProperty(definition, propertyType, description);
- boolean isSyntheticProperty = persistentProperty == null;
+ boolean isSyntheticProperty = isPersistentPropertyNull;
boolean isNotWritable = !isSyntheticProperty && !persistentProperty.isWritable();
boolean isJacksonReadOnly = !isSyntheticProperty && jackson.isReadOnly(persistentProperty);
@@ -224,7 +233,7 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
continue;
}
- if (persistentProperty == null) {
+ if (isPersistentPropertyNull) {
registrar.register(property, actualPropertyType);
continue;
}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryControllerIntegrationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryControllerIntegrationTests.java
index c0805c562..3081e49a2 100644
--- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryControllerIntegrationTests.java
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryControllerIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2015 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -66,7 +66,7 @@ public class RepositoryControllerIntegrationTests extends AbstractControllerInte
RepositoryLinksResource resource = controller.listRepositories().getBody();
- assertThat(resource.getLinks(), hasSize(7));
+ assertThat(resource.getLinks(), hasSize(8));
assertThat(resource.hasLink("people"), is(true));
assertThat(resource.hasLink("orders"), is(true));
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/alps/AlpsControllerIntegrationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/alps/AlpsControllerIntegrationTests.java
index fa66a3543..c870f6a35 100644
--- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/alps/AlpsControllerIntegrationTests.java
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/alps/AlpsControllerIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2015 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -17,6 +17,7 @@ package org.springframework.data.rest.webmvc.alps;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.junit.After;
@@ -199,4 +200,20 @@ public class AlpsControllerIntegrationTests extends AbstractControllerIntegratio
"$.alps.descriptors[?(@.id == 'person-representation')].descriptors[?(@.name == 'gender')][0].doc.value",
is("Male, Female, Undefined")));
}
+
+ /**
+ * @see DATAREST-753
+ */
+ @Test
+ public void alpsCanHandleGroovyDomainObjects() throws Exception {
+
+ Link profileLink = client.discoverUnique("profile");
+ Link groovyDomainObjectLink = client.discoverUnique(profileLink, "simulatedGroovyDomainClasses");
+ client.follow(groovyDomainObjectLink)//
+ .andExpect(jsonPath(
+ "$.alps.descriptors[?(@.id == 'simulatedGroovyDomainClass-representation')][0].descriptors[0].name",
+ is("name")
+ ));
+
+ }
}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/groovy/SimulatedGroovyDomainClass.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/groovy/SimulatedGroovyDomainClass.java
new file mode 100644
index 000000000..2c739f195
--- /dev/null
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/groovy/SimulatedGroovyDomainClass.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016 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.jpa.groovy;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import groovy.lang.GroovyObject;
+import groovy.lang.MetaClass;
+
+/**
+ * Simulates a Groovy domain object by extending {@link GroovyObject}.
+ *
+ * @author Greg Turnquist
+ * @see DATAREST-754
+ */
+@Entity
+public class SimulatedGroovyDomainClass implements GroovyObject {
+
+ @Id @GeneratedValue private Long id;
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ protected SimulatedGroovyDomainClass() {}
+
+ //
+ // The following fields don't actually have to be implemented since the test cases don't
+ // make any Groovy calls. This just simulates the structure of a Groovy object to
+ // verify proper handling.
+ //
+
+ @Override
+ public Object invokeMethod(String s, Object o) {
+ return null;
+ }
+
+ @Override
+ public Object getProperty(String s) {
+ return null;
+ }
+
+ @Override
+ public void setProperty(String s, Object o) {
+
+ }
+
+ @Override
+ public MetaClass getMetaClass() {
+ return null;
+ }
+
+ @Override
+ public void setMetaClass(MetaClass metaClass) {
+
+ }
+}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/groovy/SimulatedGroovyDomainClassRepository.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/groovy/SimulatedGroovyDomainClassRepository.java
new file mode 100644
index 000000000..90f7bd8f8
--- /dev/null
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/groovy/SimulatedGroovyDomainClassRepository.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 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.jpa.groovy;
+
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Simulates a repository built on a Groovy domain object.
+ *
+ * @author Greg Turnquist
+ * @see DATAREST-754
+ */
+public interface SimulatedGroovyDomainClassRepository extends CrudRepository {
+
+}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverterUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverterUnitTests.java
index 8579a3917..6b95964a4 100644
--- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverterUnitTests.java
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverterUnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2015 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -43,6 +43,7 @@ import org.springframework.data.rest.webmvc.mongodb.Profile;
import org.springframework.data.rest.webmvc.mongodb.User;
import org.springframework.data.rest.webmvc.mongodb.User.EmailAddress;
import org.springframework.data.rest.webmvc.mongodb.User.TypeWithPattern;
+import org.springframework.data.rest.webmvc.mongodb.groovy.SimulatedGroovyDomainClass;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -73,6 +74,7 @@ public class PersistentEntityToJsonSchemaConverterUnitTests {
config.getMetadataConfiguration().registerJsonSchemaFormat(JsonSchemaFormat.EMAIL, EmailAddress.class);
config.getMetadataConfiguration().registerFormattingPatternFor("[A-Z]+", TypeWithPattern.class);
+ config.getMetadataConfiguration().registerJsonSchemaFormat(JsonSchemaFormat.EMAIL);
config.exposeIdsFor(Profile.class);
}
@@ -159,6 +161,18 @@ public class PersistentEntityToJsonSchemaConverterUnitTests {
assertConstraints(User.class, constraints);
}
+ /**
+ * @see DATAREST-754
+ */
+ @Test
+ public void handlesGroovyDomainObjects() {
+
+ List constraints = new ArrayList();
+ constraints.add(new Constraint("$.properties.name", is(notNullValue()), "Has descriptor for name property"));
+
+ assertConstraints(SimulatedGroovyDomainClass.class, constraints);
+ }
+
@SuppressWarnings("unchecked")
private void assertConstraints(Class> type, Iterable constraints) {
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/groovy/SimulatedGroovyDomainClass.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/groovy/SimulatedGroovyDomainClass.java
new file mode 100644
index 000000000..2701bf6ee
--- /dev/null
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/groovy/SimulatedGroovyDomainClass.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2016 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.mongodb.groovy;
+
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import groovy.lang.GroovyObject;
+import groovy.lang.MetaClass;
+
+/**
+ * Simulates a Groovy domain object by extending {@link GroovyObject}.
+ *
+ * @author Greg Turnquist
+ * @see DATAREST-754
+ */
+@Document
+public class SimulatedGroovyDomainClass implements GroovyObject {
+
+ private String id;
+ private String name;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ //
+ // The following fields don't actually have to be implemented since the test cases don't
+ // make any Groovy calls. This just simulates the structure of a Groovy object to
+ // verify proper handling.
+ //
+
+ @Override
+ public Object invokeMethod(String s, Object o) {
+ return null;
+ }
+
+ @Override
+ public Object getProperty(String s) {
+ return null;
+ }
+
+ @Override
+ public void setProperty(String s, Object o) {
+
+ }
+
+ @Override
+ public MetaClass getMetaClass() {
+ return null;
+ }
+
+ @Override
+ public void setMetaClass(MetaClass metaClass) {
+
+ }
+}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/groovy/SimulatedGroovyDomainClassRepository.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/groovy/SimulatedGroovyDomainClassRepository.java
new file mode 100644
index 000000000..b11e50699
--- /dev/null
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/groovy/SimulatedGroovyDomainClassRepository.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 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.mongodb.groovy;
+
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Simulates a repository built on a Groovy domain object.
+ *
+ * @author Greg Turnquist
+ * @see DATAREST-754
+ */
+public interface SimulatedGroovyDomainClassRepository extends CrudRepository {
+
+}