DATAREST-774 - Separated integration tests from core project to avoid classpath overlap.
Extracted store specific tests into separate test modules to prevent classpath overlap between projects. Those tests are now executed in an "it" build profile to prevent the tests being packaged for distribution on release. Use Map-based repositories and mapping contexts for test in the Core and WebMvc module. Slightly changed the configuration API for lookup types on RepositoryRestConfiguration. Related ticket: DATAREST-776.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class Address {
|
||||
|
||||
public @Id @GeneratedValue Long id;
|
||||
public @Version Long version;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface AddressRepository extends CrudRepository<Address, Long> {
|
||||
|
||||
@Override
|
||||
@RestResource(exported = false)
|
||||
Iterable<Address> findAll();
|
||||
|
||||
@Override
|
||||
@RestResource(exported = false)
|
||||
<S extends Address> S save(S entity);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToMany;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class Author {
|
||||
|
||||
@Id @GeneratedValue//
|
||||
Long id;
|
||||
public String name;
|
||||
|
||||
@ManyToMany(mappedBy = "authors")//
|
||||
public Set<Book> books = new HashSet<Book>();
|
||||
|
||||
protected Author() {}
|
||||
|
||||
public Author(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface AuthorRepository extends CrudRepository<Author, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import org.springframework.data.rest.webmvc.RepositoryRestController;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
/**
|
||||
* Sample custom controller to test the ability to override
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RepositoryRestController
|
||||
public class AuthorsController {
|
||||
|
||||
@RequestMapping(value = "/authors/{author}", method = RequestMethod.DELETE)
|
||||
HttpEntity<?> deleteAuthor(@PathVariable Author author) {
|
||||
|
||||
Assert.notNull(author, "Author must not be null!");
|
||||
return new ResponseEntity<Object>(HttpStatus.I_AM_A_TEAPOT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToMany;
|
||||
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class Book {
|
||||
|
||||
public @Id @GeneratedValue Long id;
|
||||
public String isbn, title;
|
||||
|
||||
@ManyToMany(cascade = { CascadeType.MERGE }) //
|
||||
@RestResource(path = "creators") //
|
||||
public Set<Author> authors;
|
||||
|
||||
protected Book() {}
|
||||
|
||||
public Book(String isbn, String title, Iterable<Author> authors) {
|
||||
|
||||
this.isbn = isbn;
|
||||
this.title = title;
|
||||
|
||||
this.authors = new HashSet<Author>();
|
||||
|
||||
for (Author author : authors) {
|
||||
author.books.add(this);
|
||||
this.authors.add(author);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import org.springframework.data.rest.core.config.Projection;
|
||||
|
||||
/**
|
||||
* Interface for an excerpt projection for {@link Book}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Projection(name = "excerpt", types = Book.class)
|
||||
public interface BookExcerpt {
|
||||
|
||||
String getTitle();
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.rest.webmvc.spi.BackendIdConverter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link BackendIdConverter} artificially transforming the actual book id into some magic {@link String} and back.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class BookIdConverter implements BackendIdConverter {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.support.BackendIdConverter#fromRequestId(java.lang.String, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public Serializable fromRequestId(String id, Class<?> entityType) {
|
||||
return Long.parseLong(id.substring(0, id.indexOf('-')));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.support.BackendIdConverter#toRequestId(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public String toRequestId(Serializable id, Class<?> entityType) {
|
||||
|
||||
Long longId = (Long) id;
|
||||
List<Long> ids = new ArrayList<Long>(longId.intValue());
|
||||
|
||||
for (int i = 0; i < longId; i++) {
|
||||
ids.add(longId);
|
||||
}
|
||||
|
||||
return StringUtils.collectionToDelimitedString(ids, "-");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.plugin.core.Plugin#supports(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean supports(Class<?> delimiter) {
|
||||
return Book.class.equals(delimiter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RepositoryRestResource(excerptProjection = BookExcerpt.class)
|
||||
public interface BookRepository extends CrudRepository<Book, Long> {
|
||||
|
||||
@RestResource(rel = "find-by-sorted")
|
||||
List<Book> findBy(Sort sort);
|
||||
|
||||
@Query("select b from Book b where :author member of b.authors")
|
||||
List<Book> findByAuthorsContains(@Param("author") Author author);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class CreditCard {
|
||||
|
||||
@Id Long id;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
interface CreditCardRepository extends CrudRepository<CreditCard, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2015-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;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Gierke
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
@Entity
|
||||
public class Item {
|
||||
|
||||
private @Id @GeneratedValue Long id;
|
||||
private String name;
|
||||
private @JsonIgnore @OneToOne User owner;
|
||||
private @OneToOne User manager, curator;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public User getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(User owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public User getManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
public void setManager(User manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public User getCurator() {
|
||||
return curator;
|
||||
}
|
||||
|
||||
public void setCurator(User curator) {
|
||||
this.curator = curator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2015-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;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Gierke
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
public interface ItemRepository extends CrudRepository<Item, Long> {}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class LineItem {
|
||||
|
||||
@Id @GeneratedValue//
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
public LineItem(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected LineItem() {
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "ORDERS")
|
||||
public class Order {
|
||||
|
||||
@Id @GeneratedValue//
|
||||
private Long id;
|
||||
@ManyToOne(fetch = FetchType.LAZY)//
|
||||
private Person creator;
|
||||
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)//
|
||||
private List<LineItem> lineItems = new ArrayList<LineItem>();
|
||||
private Type type = Type.TAKE_AWAY;
|
||||
|
||||
public Order(Person creator) {
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
protected Order() {
|
||||
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Person getCreator() {
|
||||
return creator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lineItems
|
||||
*/
|
||||
public List<LineItem> getLineItems() {
|
||||
return lineItems;
|
||||
}
|
||||
|
||||
public void add(LineItem item) {
|
||||
this.lineItems.add(item);
|
||||
}
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return new BigDecimal(2.50);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.rest.core.annotation.Description;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RepositoryRestResource(collectionResourceDescription = @Description("Collection resource description"),
|
||||
itemResourceDescription = @Description("Item resource description."))
|
||||
public interface OrderRepository extends CrudRepository<Order, Long> {
|
||||
|
||||
List<Order> findByType(@Param("type") Type type);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.springframework.data.rest.core.annotation.Description;
|
||||
import org.springframework.data.rest.core.config.Projection;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Projection(name = "summary", types = Order.class)
|
||||
@Description("A summary of an order.")
|
||||
public interface OrderSummary {
|
||||
|
||||
@Description("Price!!")
|
||||
BigDecimal getPrice();
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
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.core.annotation.Description;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* An entity that represents a person.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
@Entity
|
||||
@JsonIgnoreProperties({ "height", "weight" })
|
||||
public class Person {
|
||||
|
||||
@Id @GeneratedValue 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") //
|
||||
@ManyToMany //
|
||||
private List<Person> siblings = new ArrayList<Person>();
|
||||
|
||||
@ManyToOne //
|
||||
private Person father;
|
||||
|
||||
@Description("Timestamp this person object was created") //
|
||||
private Date created;
|
||||
|
||||
@JsonIgnore //
|
||||
private int age;
|
||||
|
||||
private int height, weight;
|
||||
private Gender gender;
|
||||
|
||||
public Person() {}
|
||||
|
||||
public Person(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public List<Person> getSiblings() {
|
||||
return siblings;
|
||||
}
|
||||
|
||||
public void setSiblings(List<Person> siblings) {
|
||||
this.siblings = siblings;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public void setWeight(int weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public Gender getGender() {
|
||||
return gender;
|
||||
}
|
||||
|
||||
public void setGender(Gender gender) {
|
||||
this.gender = gender;
|
||||
}
|
||||
|
||||
public static enum Gender {
|
||||
MALE, FEMALE, UNDEFINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
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.core.annotation.RepositoryRestResource;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
|
||||
/**
|
||||
* A repository to manage {@link Person}s.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RepositoryRestResource(collectionResourceRel = "people", path = "people")
|
||||
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
|
||||
|
||||
@RestResource(rel = "firstname", path = "firstname")
|
||||
Page<Person> findByFirstName(@Param("firstname") String firstName, Pageable pageable);
|
||||
|
||||
@RestResource(rel = "lastname", path = "lastname")
|
||||
List<Person> findByLastName(@Param("lastname") String lastName, Sort sort);
|
||||
|
||||
Person findFirstPersonByFirstName(@Param("firstname") String firstName);
|
||||
|
||||
Page<Person> findByCreatedGreaterThan(@Param("date") Date date, Pageable pageable);
|
||||
|
||||
@Query("select p from Person p where p.created > :date")
|
||||
Page<Person> findByCreatedUsingISO8601Date(@Param("date") @DateTimeFormat(iso = ISO.DATE_TIME) Date date,
|
||||
Pageable pageable);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import org.springframework.data.rest.core.config.Projection;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Projection(name = "excerpt", types = Person.class)
|
||||
public interface PersonSummary {
|
||||
|
||||
String getFirstName();
|
||||
|
||||
String getLastName();
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* An entity that represents a receipt.
|
||||
*
|
||||
* @author Pablo Lozano
|
||||
*/
|
||||
@Entity
|
||||
@JsonIgnoreProperties({"version"})
|
||||
public class Receipt {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String saleItem;
|
||||
|
||||
private BigDecimal amount;
|
||||
|
||||
@Version
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date version;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getSaleItem() {
|
||||
return saleItem;
|
||||
}
|
||||
|
||||
public void setSaleItem(String saleItem) {
|
||||
this.saleItem = saleItem;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(BigDecimal amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
|
||||
public Date getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Date version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* A repository to manage {@link Receipt}s.
|
||||
*
|
||||
* @author Pablo Lozano
|
||||
*/
|
||||
|
||||
public interface ReceiptRepository extends CrudRepository<Receipt, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
IN_STORE, TAKE_AWAY;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2015-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;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Gierke
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
@Entity
|
||||
public class User {
|
||||
|
||||
private @Id @GeneratedValue Long id;
|
||||
private String name;
|
||||
private @JsonIgnore String password;
|
||||
|
||||
private String[] roles;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String[] getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(String... roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2015-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;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
* @soundtrack Elen - Sink like a stone (Elen)
|
||||
*/
|
||||
public interface UserExcerpt {
|
||||
|
||||
UserExcerpt getFather();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2015-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;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Gierke
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
interface UserRepository extends CrudRepository<User, Long> {}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.rest.tests.TestMvcClient.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link RepositoryController}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
@Transactional
|
||||
public class RepositoryControllerIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
@Autowired RepositoryController controller;
|
||||
|
||||
/**
|
||||
* @see DATAREST-333
|
||||
*/
|
||||
@Test
|
||||
public void rootResourceExposesGetOnly() {
|
||||
|
||||
HttpEntity<?> response = controller.optionsForRepositories();
|
||||
assertAllowHeaders(response, HttpMethod.GET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-333, DATAREST-330
|
||||
*/
|
||||
@Test
|
||||
public void headRequestReturnsNoContent() {
|
||||
assertThat(controller.headForRepositories().getStatusCode(), is(HttpStatus.NO_CONTENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-160, DATAREST-333, DATAREST-463
|
||||
*/
|
||||
@Test
|
||||
public void exposesLinksToRepositories() {
|
||||
|
||||
RepositoryLinksResource resource = controller.listRepositories().getBody();
|
||||
|
||||
assertThat(resource.getLinks(), hasSize(8));
|
||||
|
||||
assertThat(resource.hasLink("people"), is(true));
|
||||
assertThat(resource.hasLink("orders"), is(true));
|
||||
assertThat(resource.hasLink("addresses"), is(true));
|
||||
assertThat(resource.hasLink("books"), is(true));
|
||||
assertThat(resource.hasLink("authors"), is(true));
|
||||
assertThat(resource.hasLink("receipts"), is(true));
|
||||
assertThat(resource.hasLink("items"), is(true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.rest.tests.TestMvcClient.*;
|
||||
import static org.springframework.http.HttpMethod.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.support.RepositoryInvoker;
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.webmvc.jpa.Address;
|
||||
import org.springframework.data.rest.webmvc.jpa.AddressRepository;
|
||||
import org.springframework.data.rest.webmvc.jpa.CreditCard;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.data.rest.webmvc.jpa.Order;
|
||||
import org.springframework.data.rest.webmvc.jpa.Person;
|
||||
import org.springframework.data.rest.webmvc.support.DefaultedPageable;
|
||||
import org.springframework.data.rest.webmvc.support.ETag;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link RepositoryEntityController}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Jeremy Rickard
|
||||
*/
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
@Transactional
|
||||
public class RepositoryEntityControllerIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
@Autowired RepositoryEntityController controller;
|
||||
@Autowired AddressRepository repository;
|
||||
@Autowired RepositoryRestConfiguration configuration;
|
||||
@Autowired PersistentEntityResourceAssembler assembler;
|
||||
@Autowired PersistentEntities entities;
|
||||
|
||||
/**
|
||||
* @see DATAREST-217
|
||||
*/
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
public void returnsNotFoundForListingEntitiesIfFindAllNotExported() throws Exception {
|
||||
|
||||
repository.save(new Address());
|
||||
|
||||
RootResourceInformation request = getResourceInformation(Address.class);
|
||||
controller.getCollectionResource(request, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-217
|
||||
*/
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
public void rejectsEntityCreationIfSaveIsNotExported() throws Exception {
|
||||
|
||||
RootResourceInformation request = getResourceInformation(Address.class);
|
||||
|
||||
controller.postCollectionResource(request, null, null, MediaType.APPLICATION_JSON_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-301
|
||||
*/
|
||||
@Test
|
||||
public void setsExpandedSelfUriInLocationHeader() throws Exception {
|
||||
|
||||
RootResourceInformation information = getResourceInformation(Order.class);
|
||||
|
||||
PersistentEntityResource persistentEntityResource = PersistentEntityResource
|
||||
.build(new Order(new Person()), entities.getPersistentEntity(Order.class)).build();
|
||||
|
||||
ResponseEntity<?> entity = controller.putItemResource(information, persistentEntityResource, 1L, assembler,
|
||||
ETag.NO_ETAG, MediaType.APPLICATION_JSON_VALUE);
|
||||
|
||||
assertThat(entity.getHeaders().getLocation().toString(), not(Matchers.endsWith("{?projection}")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test
|
||||
public void exposesHeadForCollectionResourceIfExported() throws Exception {
|
||||
ResponseEntity<?> entity = controller.headCollectionResource(getResourceInformation(Person.class),
|
||||
new DefaultedPageable(null, false));
|
||||
assertThat(entity.getStatusCode(), is(HttpStatus.NO_CONTENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void doesNotExposeHeadForCollectionResourceIfNotExported() throws Exception {
|
||||
controller.headCollectionResource(getResourceInformation(CreditCard.class), new DefaultedPageable(null, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test
|
||||
public void exposesHeadForItemResourceIfExported() throws Exception {
|
||||
|
||||
Address address = repository.save(new Address());
|
||||
|
||||
ResponseEntity<?> entity = controller.headForItemResource(getResourceInformation(Address.class), address.id,
|
||||
assembler);
|
||||
|
||||
assertThat(entity.getStatusCode(), is(HttpStatus.NO_CONTENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void doesNotExposeHeadForItemResourceIfNotExisting() throws Exception {
|
||||
controller.headForItemResource(getResourceInformation(CreditCard.class), 1L, assembler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-333
|
||||
*/
|
||||
@Test
|
||||
public void doesNotExposeMethodsForOptionsIfNotHttpMethodsSupportedForCollectionResource() {
|
||||
|
||||
HttpEntity<?> response = controller.optionsForCollectionResource(getResourceInformation(Address.class));
|
||||
assertAllowHeaders(response, OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-333
|
||||
*/
|
||||
@Test
|
||||
public void exposesSupportedHttpMethodsInAllowHeaderForOptionsRequestToCollectionResource() {
|
||||
|
||||
HttpEntity<?> response = controller.optionsForCollectionResource(getResourceInformation(Person.class));
|
||||
assertAllowHeaders(response, GET, POST, HEAD, OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-333
|
||||
*/
|
||||
@Test
|
||||
public void exposesSupportedHttpMethodsInAllowHeaderForOptionsRequestToItemResource() {
|
||||
|
||||
HttpEntity<?> response = controller.optionsForItemResource(getResourceInformation(Person.class));
|
||||
assertAllowHeaders(response, GET, PUT, PATCH, DELETE, HEAD, OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-333, DATAREST-348
|
||||
*/
|
||||
@Test
|
||||
public void optionsForItermResourceSetsAllowPatchHeader() {
|
||||
|
||||
ResponseEntity<?> entity = controller.optionsForItemResource(getResourceInformation(Person.class));
|
||||
|
||||
List<String> value = entity.getHeaders().get("Accept-Patch");
|
||||
|
||||
assertThat(value, hasSize(3));
|
||||
assertThat(value,
|
||||
hasItems(//
|
||||
RestMediaTypes.JSON_PATCH_JSON.toString(), //
|
||||
RestMediaTypes.MERGE_PATCH_JSON.toString(), //
|
||||
MediaType.APPLICATION_JSON_VALUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-34
|
||||
*/
|
||||
@Test
|
||||
public void returnsBodyOnPutForUpdateIfAcceptHeaderPresentByDefault() throws Exception {
|
||||
|
||||
RootResourceInformation request = getResourceInformation(Order.class);
|
||||
Order order = request.getInvoker().invokeSave(new Order(new Person()));
|
||||
|
||||
PersistentEntityResource persistentEntityResource = PersistentEntityResource
|
||||
.build(new Order(new Person()), entities.getPersistentEntity(Order.class)).build();
|
||||
|
||||
assertThat(controller.putItemResource(request, persistentEntityResource, order.getId(), assembler, ETag.NO_ETAG,
|
||||
MediaType.APPLICATION_JSON_VALUE).hasBody(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-34
|
||||
*/
|
||||
@Test
|
||||
public void returnsBodyForCreatingPutIfAcceptHeaderPresentByDefault() throws HttpRequestMethodNotSupportedException {
|
||||
|
||||
RootResourceInformation request = getResourceInformation(Order.class);
|
||||
PersistentEntityResource persistentEntityResource = PersistentEntityResource
|
||||
.build(new Order(new Person()), entities.getPersistentEntity(Order.class)).build();
|
||||
|
||||
assertThat(controller.putItemResource(request, persistentEntityResource, 1L, assembler, ETag.NO_ETAG,
|
||||
MediaType.APPLICATION_JSON_VALUE).hasBody(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-34
|
||||
*/
|
||||
@Test
|
||||
public void returnsBodyForPostIfAcceptHeaderIsPresentByDefault() throws Exception {
|
||||
|
||||
RootResourceInformation request = getResourceInformation(Order.class);
|
||||
PersistentEntityResource persistentEntityResource = PersistentEntityResource
|
||||
.build(new Order(new Person()), entities.getPersistentEntity(Order.class)).build();
|
||||
|
||||
assertThat(controller
|
||||
.postCollectionResource(request, persistentEntityResource, assembler, MediaType.APPLICATION_JSON_VALUE)
|
||||
.hasBody(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-34
|
||||
*/
|
||||
@Test
|
||||
public void doesNotReturnBodyForPostIfNoAcceptHeaderPresentByDefault() throws Exception {
|
||||
|
||||
RootResourceInformation request = getResourceInformation(Order.class);
|
||||
PersistentEntityResource persistentEntityResource = PersistentEntityResource
|
||||
.build(new Order(new Person()), entities.getPersistentEntity(Order.class)).build();
|
||||
|
||||
assertThat(controller.postCollectionResource(request, persistentEntityResource, assembler, null).hasBody(),
|
||||
is(false));
|
||||
assertThat(controller.postCollectionResource(request, persistentEntityResource, assembler, "").hasBody(),
|
||||
is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-581
|
||||
*/
|
||||
@Test
|
||||
public void createsEtagForProjectedEntityCorrectly() throws Exception {
|
||||
|
||||
Address address = repository.save(new Address());
|
||||
|
||||
PersistentEntityResourceAssembler assembler = Mockito.mock(PersistentEntityResourceAssembler.class);
|
||||
AddressProjection addressProjection = new SpelAwareProxyProjectionFactory()
|
||||
.createProjection(AddressProjection.class);
|
||||
|
||||
PersistentEntityResource resource = PersistentEntityResource
|
||||
.build(addressProjection, entities.getPersistentEntity(Address.class)).build();
|
||||
|
||||
Mockito.when(assembler.toFullResource(Mockito.any(Object.class))).thenReturn(resource);
|
||||
|
||||
ResponseEntity<Resource<?>> entity = controller.getItemResource(getResourceInformation(Address.class), address.id,
|
||||
assembler, new LinkedMultiValueMap<String, String>());
|
||||
|
||||
assertThat(entity.getHeaders().getETag(), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-724
|
||||
*/
|
||||
@Test
|
||||
public void deletesEntityWithCustomLookupCorrectly() throws Exception {
|
||||
|
||||
Address address = repository.save(new Address());
|
||||
assertThat(repository.findOne(address.id), is(notNullValue()));
|
||||
|
||||
RootResourceInformation resourceInformation = getResourceInformation(Address.class);
|
||||
RepositoryInvoker invoker = spy(resourceInformation.getInvoker());
|
||||
doReturn(address).when(invoker).invokeFindOne("foo");
|
||||
|
||||
RootResourceInformation informationSpy = Mockito.spy(resourceInformation);
|
||||
doReturn(invoker).when(informationSpy).getInvoker();
|
||||
|
||||
controller.deleteItemResource(informationSpy, "foo", ETag.from("0"));
|
||||
|
||||
assertThat(repository.findOne(address.id), is(nullValue()));
|
||||
}
|
||||
|
||||
interface AddressProjection {}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2015-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;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.webmvc.jpa.Book;
|
||||
import org.springframework.data.rest.webmvc.jpa.BookRepository;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.data.rest.webmvc.jpa.TestDataPopulator;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
@Transactional
|
||||
public class RepositoryPropertyReferenceControllerIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
@Autowired RepositoryPropertyReferenceController controller;
|
||||
@Autowired TestDataPopulator populator;
|
||||
@Autowired BookRepository books;
|
||||
|
||||
PersistentEntityResourceAssembler assembler;
|
||||
RootResourceInformation information;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
this.assembler = mock(PersistentEntityResourceAssembler.class);
|
||||
this.information = getResourceInformation(Book.class);
|
||||
this.populator.populateRepositories();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exposesResourceForCustomizedPropertyResourcePath() throws Exception {
|
||||
|
||||
Book book = books.findAll().iterator().next();
|
||||
|
||||
assertThat(controller.followPropertyReference(information, book.id, "creators", assembler).getStatusCode(),
|
||||
is(HttpStatus.OK));
|
||||
}
|
||||
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void doesNotExposeOriginalPathIfPropertyResourcePathIsCustomized() throws Exception {
|
||||
|
||||
Book book = books.findAll().iterator().next();
|
||||
|
||||
controller.followPropertyReference(information, book.id, "authors", assembler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.rest.tests.TestMvcClient.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMetadata;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.tests.ResourceTester;
|
||||
import org.springframework.data.rest.tests.ResourceTester.HasSelfLink;
|
||||
import org.springframework.data.rest.webmvc.jpa.Address;
|
||||
import org.springframework.data.rest.webmvc.jpa.Author;
|
||||
import org.springframework.data.rest.webmvc.jpa.Book;
|
||||
import org.springframework.data.rest.webmvc.jpa.CreditCard;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.data.rest.webmvc.jpa.Person;
|
||||
import org.springframework.data.rest.webmvc.jpa.TestDataPopulator;
|
||||
import org.springframework.data.rest.webmvc.support.DefaultedPageable;
|
||||
import org.springframework.hateoas.PagedResources;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link RepositorySearchController}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
@Transactional
|
||||
public class RepositorySearchControllerIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
static final DefaultedPageable PAGEABLE = new DefaultedPageable(new PageRequest(0, 10), true);
|
||||
|
||||
@Autowired TestDataPopulator loader;
|
||||
@Autowired RepositorySearchController controller;
|
||||
@Autowired PersistentEntityResourceAssembler assembler;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
loader.populateRepositories();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rendersCorrectSearchLinksForPersons() throws Exception {
|
||||
|
||||
RootResourceInformation request = getResourceInformation(Person.class);
|
||||
ResourceSupport resource = controller.listSearches(request);
|
||||
|
||||
ResourceTester tester = ResourceTester.of(resource);
|
||||
tester.assertNumberOfLinks(6); // Self link included
|
||||
tester.assertHasLinkEndingWith("findFirstPersonByFirstName", "findFirstPersonByFirstName{?firstname,projection}");
|
||||
tester.assertHasLinkEndingWith("firstname", "firstname{?firstname,page,size,sort,projection}");
|
||||
tester.assertHasLinkEndingWith("lastname", "lastname{?lastname,sort,projection}");
|
||||
tester.assertHasLinkEndingWith("findByCreatedUsingISO8601Date",
|
||||
"findByCreatedUsingISO8601Date{?date,page,size,sort,projection}");
|
||||
tester.assertHasLinkEndingWith("findByCreatedGreaterThan",
|
||||
"findByCreatedGreaterThan{?date,page,size,sort,projection}");
|
||||
}
|
||||
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void returns404ForUnexportedRepository() {
|
||||
controller.listSearches(getResourceInformation(CreditCard.class));
|
||||
}
|
||||
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void returns404ForRepositoryWithoutSearches() {
|
||||
controller.listSearches(getResourceInformation(Author.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executesSearchAgainstRepository() {
|
||||
|
||||
RootResourceInformation resourceInformation = getResourceInformation(Person.class);
|
||||
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>(1);
|
||||
parameters.add("firstname", "John");
|
||||
|
||||
ResponseEntity<Object> response = controller.executeSearch(resourceInformation, parameters, "firstname", PAGEABLE,
|
||||
null, assembler);
|
||||
|
||||
ResourceTester tester = ResourceTester.of(response.getBody());
|
||||
PagedResources<Object> pagedResources = tester.assertIsPage();
|
||||
assertThat(pagedResources.getContent().size(), is(1));
|
||||
|
||||
ResourceMetadata metadata = getMetadata(Person.class);
|
||||
tester.withContentResource(new HasSelfLink(BASE.slash(metadata.getPath()).slash("{id}")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void doesNotExposeHeadForSearchResourceIfResourceDoesnHaveSearches() {
|
||||
controller.headForSearches(getResourceInformation(Author.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void exposesHeadForSearchResourceIfResourceIsNotExposed() {
|
||||
controller.headForSearches(getResourceInformation(CreditCard.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test
|
||||
public void exposesHeadForSearchResourceIfResourceIsExposed() {
|
||||
controller.headForSearches(getResourceInformation(Person.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test
|
||||
public void exposesHeadForExistingQueryMethodResource() {
|
||||
controller.headForSearch(getResourceInformation(Person.class), "findByCreatedUsingISO8601Date");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-330
|
||||
*/
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void doesNotExposeHeadForInvalidQueryMethodResource() {
|
||||
controller.headForSearch(getResourceInformation(Person.class), "foobar");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-333
|
||||
*/
|
||||
@Test
|
||||
public void searchResourceSupportsGetOnly() {
|
||||
assertAllowHeaders(controller.optionsForSearches(getResourceInformation(Person.class)), HttpMethod.GET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-333
|
||||
*/
|
||||
@Test(expected = ResourceNotFoundException.class)
|
||||
public void returns404ForOptionsForRepositoryWithoutSearches() {
|
||||
controller.optionsForSearches(getResourceInformation(Address.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-333
|
||||
*/
|
||||
@Test
|
||||
public void queryMethodResourceSupportsGetOnly() {
|
||||
|
||||
RootResourceInformation resourceInformation = getResourceInformation(Person.class);
|
||||
HttpEntity<Object> response = controller.optionsForSearch(resourceInformation, "firstname");
|
||||
|
||||
assertAllowHeaders(response, HttpMethod.GET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-502
|
||||
*/
|
||||
@Test
|
||||
public void interpretsUriAsReferenceToRelatedEntity() {
|
||||
|
||||
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>(1);
|
||||
parameters.add("author", "/author/1");
|
||||
|
||||
RootResourceInformation resourceInformation = getResourceInformation(Book.class);
|
||||
|
||||
ResponseEntity<Object> result = controller.executeSearch(resourceInformation, parameters, "findByAuthorsContains",
|
||||
PAGEABLE, null, assembler);
|
||||
|
||||
assertThat(result.getBody(), is(instanceOf(Resources.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-515
|
||||
*/
|
||||
@Test
|
||||
public void repositorySearchResourceExposesDomainType() {
|
||||
|
||||
RepositorySearchesResource searches = controller.listSearches(getResourceInformation(Person.class));
|
||||
|
||||
assertThat(searches.getDomainType(), is(typeCompatibleWith(Person.class)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.rest.core.mapping.ResourceType.*;
|
||||
import static org.springframework.http.HttpMethod.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.data.rest.core.mapping.SupportedHttpMethods;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.webmvc.jpa.Address;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link RootResourceInformation}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
@Transactional
|
||||
public class RootResourceInformationIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
/**
|
||||
* @see DATAREST-217
|
||||
*/
|
||||
@Test
|
||||
public void getIsNotSupportedIfFindAllIsNotExported() {
|
||||
|
||||
SupportedHttpMethods supportedMethods = getResourceInformation(Address.class).getSupportedMethods();
|
||||
assertThat(supportedMethods.getMethodsFor(COLLECTION), not(hasItem(GET)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-217
|
||||
*/
|
||||
@Test
|
||||
public void postIsNotSupportedIfSaveIsNotExported() {
|
||||
|
||||
SupportedHttpMethods supportedMethods = getResourceInformation(Address.class).getSupportedMethods();
|
||||
assertThat(supportedMethods.getMethodsFor(COLLECTION), not(hasItem(POST)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.alps;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.tests.TestMvcClient;
|
||||
import org.springframework.data.rest.webmvc.ProfileController;
|
||||
import org.springframework.data.rest.webmvc.RestMediaTypes;
|
||||
import org.springframework.data.rest.webmvc.alps.AlpsController;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
|
||||
import org.springframework.data.rest.webmvc.jpa.Item;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.LinkDiscoverer;
|
||||
import org.springframework.hateoas.LinkDiscoverers;
|
||||
import org.springframework.hateoas.core.JsonPathLinkDiscoverer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link AlpsController}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { JpaRepositoryConfig.class, AlpsControllerIntegrationTests.Config.class })
|
||||
public class AlpsControllerIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
@Autowired WebApplicationContext context;
|
||||
@Autowired LinkDiscoverers discoverers;
|
||||
@Autowired RepositoryRestConfiguration configuration;
|
||||
|
||||
@Configuration
|
||||
static class Config extends RepositoryRestConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public LinkDiscoverer alpsLinkDiscoverer() {
|
||||
return new JsonPathLinkDiscoverer("$.descriptors[?(@.name == '%s')].href",
|
||||
MediaType.valueOf("application/alps+json"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
|
||||
config.exposeIdsFor(Item.class);
|
||||
}
|
||||
}
|
||||
|
||||
TestMvcClient client;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||
this.client = new TestMvcClient(mvc, this.discoverers);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
configuration.setEnableEnumTranslation(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-230
|
||||
*/
|
||||
@Test
|
||||
public void exposesAlpsCollectionResources() throws Exception {
|
||||
|
||||
Link profileLink = client.discoverUnique("profile");
|
||||
Link peopleLink = client.discoverUnique(profileLink, "people", MediaType.ALL);
|
||||
|
||||
client.follow(peopleLink, RestMediaTypes.ALPS_JSON)//
|
||||
.andExpect(jsonPath("$.alps.version").value("1.0"))//
|
||||
.andExpect(jsonPath("$.alps.descriptors[*].name", hasItems("people", "person")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-638
|
||||
*/
|
||||
@Test
|
||||
public void verifyThatAlpsIsDefaultProfileFormat() throws Exception {
|
||||
|
||||
Link profileLink = client.discoverUnique("profile");
|
||||
Link peopleLink = client.discoverUnique(profileLink, "people", MediaType.ALL);
|
||||
|
||||
client.follow(peopleLink)//
|
||||
.andExpect(jsonPath("$.alps.version").value("1.0"))//
|
||||
.andExpect(jsonPath("$.alps.descriptors[*].name", hasItems("people", "person")));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
@Test
|
||||
public void verifyThatAttributesIgnoredDontAppearInAlps() throws Exception {
|
||||
|
||||
Link profileLink = client.discoverUnique("profile");
|
||||
Link itemsLink = client.discoverUnique(profileLink, "items", MediaType.ALL);
|
||||
|
||||
client.follow(itemsLink, RestMediaTypes.ALPS_JSON)//
|
||||
// Exposes standard property
|
||||
.andExpect(jsonPath("$.alps.descriptors[*].descriptors[*].name", hasItems("name")))
|
||||
// Does not expose explicitly @JsonIgnored property
|
||||
.andExpect(jsonPath("$.alps.descriptors[*].descriptors[*].name", not(hasItems("owner"))))
|
||||
// Does not expose properties pointing to non exposed types
|
||||
.andExpect(jsonPath("$.alps.descriptors[*].descriptors[*].name", not(hasItems("manager", "curator"))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-494
|
||||
*/
|
||||
@Test
|
||||
public void linksToJsonSchemaFromRepresentationDescriptor() throws Exception {
|
||||
|
||||
Link profileLink = client.discoverUnique("profile");
|
||||
Link itemsLink = client.discoverUnique(profileLink, "items", MediaType.ALL);
|
||||
|
||||
assertThat(itemsLink, is(notNullValue()));
|
||||
|
||||
client.follow(itemsLink, RestMediaTypes.ALPS_JSON)//
|
||||
.andExpect(
|
||||
jsonPath("$.alps.descriptors[?(@.id == 'item-representation')][0].href", endsWith("/profile/items")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-516
|
||||
*/
|
||||
@Test
|
||||
public void referenceToAssociatedEntityDesciptorPointsToRepresentationDescriptor() throws Exception {
|
||||
|
||||
Link profileLink = client.discoverUnique("profile");
|
||||
Link usersLink = client.discoverUnique(profileLink, "people", MediaType.ALL);
|
||||
|
||||
String jsonPath = "$.alps."; // Root
|
||||
jsonPath += "descriptors[?(@.id == 'person-representation')]."; // Representation descriptor
|
||||
jsonPath += "descriptors[?(@.name == 'father')][0]."; // First father descriptor
|
||||
jsonPath += "rt"; // Return type
|
||||
|
||||
client.follow(usersLink, RestMediaTypes.ALPS_JSON)//
|
||||
.andExpect(jsonPath(jsonPath,
|
||||
allOf(containsString(ProfileController.PROFILE_ROOT_MAPPING), endsWith("-representation"))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-630
|
||||
*/
|
||||
@Test
|
||||
public void onlyExposesIdAttributesWhenExposedInTheConfiguration() throws Exception {
|
||||
|
||||
Link profileLink = client.discoverUnique("profile");
|
||||
Link itemsLink = client.discoverUnique(profileLink, "items", MediaType.ALL);
|
||||
|
||||
client.follow(itemsLink, RestMediaTypes.ALPS_JSON)//
|
||||
// Exposes identifier if configured to
|
||||
.andExpect(jsonPath("$.alps.descriptors[*].descriptors[*].name", hasItems("id", "name")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-683
|
||||
*/
|
||||
@Test
|
||||
public void enumValueListingsAreTranslatedIfEnabled() throws Exception {
|
||||
|
||||
configuration.setEnableEnumTranslation(true);
|
||||
|
||||
Link profileLink = client.discoverUnique("profile");
|
||||
Link peopleLink = client.discoverUnique(profileLink, "people", MediaType.ALL);
|
||||
|
||||
client.follow(peopleLink)//
|
||||
.andExpect(jsonPath(
|
||||
"$.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")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext;
|
||||
import org.springframework.data.jpa.mapping.JpaPersistentEntity;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.rest.webmvc.PersistentEntityResource;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
/**
|
||||
* Integration tests for DATAREST-262, checking serialization and deserialization of associations within embeddables.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class DataRest262Tests {
|
||||
|
||||
@Configuration
|
||||
@Import({ RepositoryRestMvcConfiguration.class, JpaInfrastructureConfig.class })
|
||||
@EnableJpaRepositories(considerNestedRepositories = true)
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
@Autowired ApplicationContext beanFactory;
|
||||
@Autowired JpaMetamodelMappingContext mappingContext;
|
||||
@Autowired AirportRepository repository;
|
||||
@Autowired @Qualifier("halObjectMapper") ObjectMapper mapper;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-262
|
||||
*/
|
||||
@Test
|
||||
public void deserializesNestedAssociation() throws Exception {
|
||||
|
||||
Airport airport = repository.save(new Airport());
|
||||
String payload = "{\"orgOrDstFlightPart\":{\"airport\":\"/api/airports/" + airport.id + "\"}}";
|
||||
|
||||
AircraftMovement result = mapper.readValue(payload, AircraftMovement.class);
|
||||
assertThat(result.orgOrDstFlightPart.airport.id, is(airport.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-262
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void serializesLinksToNestedAssociations() throws Exception {
|
||||
|
||||
Airport first = new Airport();
|
||||
first.id = 1L;
|
||||
|
||||
Airport second = new Airport();
|
||||
second.id = 2L;
|
||||
|
||||
FlightPart part = new FlightPart();
|
||||
part.airport = second;
|
||||
|
||||
AircraftMovement movement = new AircraftMovement();
|
||||
movement.id = 3L;
|
||||
movement.originOrDestinationAirport = first;
|
||||
movement.orgOrDstFlightPart = part;
|
||||
|
||||
JpaPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(AircraftMovement.class);
|
||||
|
||||
Resource<Object> resource = PersistentEntityResource.build(movement, persistentEntity).//
|
||||
withLink(new Link("/api/airports/" + movement.id)).//
|
||||
build();
|
||||
|
||||
String result = mapper.writeValueAsString(resource);
|
||||
|
||||
assertThat(JsonPath.read(result, "$_links.self"), is(notNullValue()));
|
||||
assertThat(JsonPath.read(result, "$_links.airport"), is(notNullValue()));
|
||||
assertThat(JsonPath.read(result, "$_links.originOrDestinationAirport"), is(notNullValue()));
|
||||
}
|
||||
|
||||
public interface AircraftMovementRepository extends CrudRepository<AircraftMovement, Long> {
|
||||
|
||||
}
|
||||
|
||||
public interface AirportRepository extends CrudRepository<Airport, Long> {
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "aircraftmovement")
|
||||
public static class AircraftMovement {
|
||||
|
||||
@Id @GeneratedValue Long id;
|
||||
@ManyToOne Airport originOrDestinationAirport;
|
||||
@Embedded @NotNull FlightPart orgOrDstFlightPart;
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class FlightPart {
|
||||
@ManyToOne Airport airport;
|
||||
}
|
||||
|
||||
@Entity(name = "airport")
|
||||
public static class Airport {
|
||||
@Id @GeneratedValue Long id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2015-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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.tests.TestMvcClient;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||
import org.springframework.hateoas.LinkDiscoverer;
|
||||
import org.springframework.hateoas.LinkDiscoverers;
|
||||
import org.springframework.hateoas.core.JsonPathLinkDiscoverer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Integration tests for DATAREST-363.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(
|
||||
classes = { JpaRepositoryConfig.class, RepositoryRestMvcConfiguration.class, DataRest363Tests.Config.class })
|
||||
public class DataRest363Tests {
|
||||
|
||||
private static MediaType MEDIA_TYPE = MediaType.APPLICATION_JSON;
|
||||
|
||||
@Autowired WebApplicationContext context;
|
||||
@Autowired LinkDiscoverers discoverers;
|
||||
@Autowired PersonRepository personRepository;
|
||||
|
||||
TestMvcClient testMvcClient;
|
||||
|
||||
Person frodo;
|
||||
|
||||
@Configuration
|
||||
static class Config extends RepositoryRestConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public LinkDiscoverer classicLinkDiscover() {
|
||||
return new JsonPathLinkDiscoverer("$.links[?(@.rel == '%s')].href", MEDIA_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
|
||||
config.setDefaultMediaType(MEDIA_TYPE).useHalAsDefaultJsonMediaType(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).//
|
||||
defaultRequest(get("/")).build();
|
||||
|
||||
this.testMvcClient = new TestMvcClient(mvc, discoverers);
|
||||
this.frodo = personRepository.save(new Person("Frodo", "Baggins"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-363
|
||||
*/
|
||||
@Test
|
||||
public void testBasics() throws Exception {
|
||||
|
||||
ResultActions frodoActions = testMvcClient.follow("/people/".concat(frodo.getId().toString()));
|
||||
|
||||
frodoActions.andExpect(jsonPath("$.links").value(hasSize(4)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
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.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
public class JpaInfrastructureConfig {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||
return builder.setType(EmbeddedDatabaseType.HSQL).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean 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.setPersistenceUnitName("spring-data-rest-webmvc");
|
||||
factory.setDataSource(dataSource());
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return new JpaTransactionManager();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.data.rest.webmvc.BasePathAwareController;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
/**
|
||||
* Test configuration for JPA.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
@EnableJpaRepositories
|
||||
@EnableTransactionManagement
|
||||
public class JpaRepositoryConfig extends JpaInfrastructureConfig {
|
||||
|
||||
@Bean
|
||||
public BookIdConverter bookIdConverter() {
|
||||
return new BookIdConverter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestDataPopulator testDataPopulator() {
|
||||
return new TestDataPopulator();
|
||||
}
|
||||
|
||||
@BasePathAwareController
|
||||
static class BooksHtmlController {
|
||||
|
||||
@RequestMapping(value = "/books/{id}", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
|
||||
void person(@PathVariable String id) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,721 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.rest.webmvc.util.TestUtils.*;
|
||||
import static org.springframework.http.HttpHeaders.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import net.minidev.json.JSONArray;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMappings;
|
||||
import org.springframework.data.rest.tests.CommonWebTests;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Links;
|
||||
import org.springframework.hateoas.RelProvider;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
/**
|
||||
* Web integration tests specific to JPA.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@Transactional
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
public class JpaWebTests extends CommonWebTests {
|
||||
|
||||
private static final MediaType TEXT_URI_LIST = MediaType.valueOf("text/uri-list");
|
||||
static final String LINK_TO_SIBLINGS_OF = "$._embedded..[?(@.firstName == '%s')]._links.siblings.href[0]";
|
||||
|
||||
@Autowired TestDataPopulator loader;
|
||||
@Autowired ResourceMappings mappings;
|
||||
@Autowired RelProvider relProvider;
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.AbstractWebIntegrationTests#setUp()
|
||||
*/
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
loader.populateRepositories();
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.AbstractWebIntegrationTests#expectedRootLinkRels()
|
||||
*/
|
||||
@Override
|
||||
protected Iterable<String> expectedRootLinkRels() {
|
||||
return Arrays.asList("people", "authors", "books");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.AbstractWebIntegrationTests#getPayloadToPost()
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, String> getPayloadToPost() throws Exception {
|
||||
return Collections.singletonMap("people", readFileFromClasspath("person.json"));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.AbstractWebIntegrationTests#getRootAndLinkedResources()
|
||||
*/
|
||||
@Override
|
||||
protected MultiValueMap<String, String> getRootAndLinkedResources() {
|
||||
|
||||
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
|
||||
map.add("authors", "books");
|
||||
map.add("books", "authors");
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-99
|
||||
*/
|
||||
@Test
|
||||
public void doesNotExposeCreditCardRepository() throws Exception {
|
||||
|
||||
mvc.perform(get("/")). //
|
||||
andExpect(status().isOk()). //
|
||||
andExpect(doesNotHaveLinkWithRel(mappings.getMetadataFor(CreditCard.class).getRel()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessPersons() throws Exception {
|
||||
|
||||
MockHttpServletResponse response = client.request("/people?page=0&size=1");
|
||||
|
||||
Link nextLink = client.assertHasLinkWithRel(Link.REL_NEXT, response);
|
||||
assertDoesNotHaveLinkWithRel(Link.REL_PREVIOUS, response);
|
||||
|
||||
response = client.request(nextLink);
|
||||
client.assertHasLinkWithRel(Link.REL_PREVIOUS, response);
|
||||
nextLink = client.assertHasLinkWithRel(Link.REL_NEXT, response);
|
||||
|
||||
response = client.request(nextLink);
|
||||
client.assertHasLinkWithRel(Link.REL_PREVIOUS, response);
|
||||
assertDoesNotHaveLinkWithRel(Link.REL_NEXT, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-169
|
||||
*/
|
||||
@Test
|
||||
public void exposesLinkForRelatedResource() throws Exception {
|
||||
|
||||
MockHttpServletResponse response = client.request("/");
|
||||
Link ordersLink = client.assertHasLinkWithRel("orders", response);
|
||||
|
||||
MockHttpServletResponse orders = client.request(ordersLink);
|
||||
Link creatorLink = assertHasContentLinkWithRel("creator", orders);
|
||||
|
||||
assertThat(client.request(creatorLink), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-200
|
||||
*/
|
||||
@Test
|
||||
public void exposesInlinedEntities() throws Exception {
|
||||
|
||||
MockHttpServletResponse response = client.request("/");
|
||||
Link ordersLink = client.assertHasLinkWithRel("orders", response);
|
||||
|
||||
MockHttpServletResponse orders = client.request(ordersLink);
|
||||
assertHasJsonPathValue("$..lineItems", orders);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-199
|
||||
*/
|
||||
@Test
|
||||
public void createsOrderUsingPut() throws Exception {
|
||||
|
||||
mvc.perform(//
|
||||
put("/orders/{id}", 4711).//
|
||||
content(readFileFromClasspath("order.json")).contentType(MediaType.APPLICATION_JSON)//
|
||||
).andExpect(status().isCreated());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-117
|
||||
*/
|
||||
@Test
|
||||
public void createPersonThenVerifyIgnoredAttributesDontExist() throws Exception {
|
||||
|
||||
Link peopleLink = client.discoverUnique("people");
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
Person frodo = new Person("Frodo", "Baggins");
|
||||
frodo.setAge(77);
|
||||
frodo.setHeight(42);
|
||||
frodo.setWeight(75);
|
||||
String frodoString = mapper.writeValueAsString(frodo);
|
||||
|
||||
MockHttpServletResponse response = postAndGet(peopleLink, frodoString, MediaType.APPLICATION_JSON);
|
||||
|
||||
assertJsonPathEquals("$.firstName", "Frodo", response);
|
||||
assertJsonPathEquals("$.lastName", "Baggins", response);
|
||||
assertJsonPathDoesntExist("$.age", response);
|
||||
assertJsonPathDoesntExist("$.height", response);
|
||||
assertJsonPathDoesntExist("$.weight", response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-95
|
||||
*/
|
||||
@Test
|
||||
public void createThenPatch() throws Exception {
|
||||
|
||||
Link peopleLink = client.discoverUnique("people");
|
||||
|
||||
MockHttpServletResponse bilbo = postAndGet(peopleLink, "{ \"firstName\" : \"Bilbo\", \"lastName\" : \"Baggins\" }",
|
||||
MediaType.APPLICATION_JSON);
|
||||
|
||||
Link bilboLink = client.assertHasLinkWithRel("self", bilbo);
|
||||
|
||||
assertThat((String) JsonPath.read(bilbo.getContentAsString(), "$.firstName"), is("Bilbo"));
|
||||
assertThat((String) JsonPath.read(bilbo.getContentAsString(), "$.lastName"), is("Baggins"));
|
||||
|
||||
MockHttpServletResponse frodo = patchAndGet(bilboLink, "{ \"firstName\" : \"Frodo\" }", MediaType.APPLICATION_JSON);
|
||||
|
||||
assertThat((String) JsonPath.read(frodo.getContentAsString(), "$.firstName"), is("Frodo"));
|
||||
assertThat((String) JsonPath.read(frodo.getContentAsString(), "$.lastName"), is("Baggins"));
|
||||
|
||||
frodo = patchAndGet(bilboLink, "{ \"firstName\" : null }", MediaType.APPLICATION_JSON);
|
||||
|
||||
assertThat((String) JsonPath.read(frodo.getContentAsString(), "$.firstName"), is(nullValue()));
|
||||
assertThat((String) JsonPath.read(frodo.getContentAsString(), "$.lastName"), is("Baggins"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-150
|
||||
*/
|
||||
@Test
|
||||
public void createThenPut() throws Exception {
|
||||
|
||||
Link peopleLink = client.discoverUnique("people");
|
||||
|
||||
MockHttpServletResponse bilbo = postAndGet(peopleLink, //
|
||||
"{ \"firstName\" : \"Bilbo\", \"lastName\" : \"Baggins\" }", //
|
||||
MediaType.APPLICATION_JSON);
|
||||
|
||||
Link bilboLink = client.assertHasLinkWithRel("self", bilbo);
|
||||
|
||||
assertThat((String) JsonPath.read(bilbo.getContentAsString(), "$.firstName"), equalTo("Bilbo"));
|
||||
assertThat((String) JsonPath.read(bilbo.getContentAsString(), "$.lastName"), equalTo("Baggins"));
|
||||
|
||||
MockHttpServletResponse frodo = putAndGet(bilboLink, //
|
||||
"{ \"firstName\" : \"Frodo\" }", //
|
||||
MediaType.APPLICATION_JSON);
|
||||
|
||||
assertThat((String) JsonPath.read(frodo.getContentAsString(), "$.firstName"), equalTo("Frodo"));
|
||||
assertNull(JsonPath.read(frodo.getContentAsString(), "$.lastName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listsSiblingsWithContentCorrectly() throws Exception {
|
||||
assertPersonWithNameAndSiblingLink("John");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listsEmptySiblingsCorrectly() throws Exception {
|
||||
assertPersonWithNameAndSiblingLink("Billy Bob");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-219
|
||||
*/
|
||||
@Test
|
||||
public void manipulatePropertyCollectionRestfullyWithMultiplePosts() throws Exception {
|
||||
|
||||
List<Link> links = preparePersonResources(new Person("Frodo", "Baggins"), //
|
||||
new Person("Bilbo", "Baggins"), //
|
||||
new Person("Merry", "Baggins"), //
|
||||
new Person("Pippin", "Baggins"));
|
||||
|
||||
Link frodosSiblingLink = links.get(0);
|
||||
|
||||
patchAndGet(frodosSiblingLink, links.get(1).getHref(), TEXT_URI_LIST);
|
||||
patchAndGet(frodosSiblingLink, links.get(2).getHref(), TEXT_URI_LIST);
|
||||
patchAndGet(frodosSiblingLink, links.get(3).getHref(), TEXT_URI_LIST);
|
||||
|
||||
assertSiblingNames(frodosSiblingLink, "Bilbo", "Merry", "Pippin");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-219
|
||||
*/
|
||||
@Test
|
||||
public void manipulatePropertyCollectionRestfullyWithSinglePost() throws Exception {
|
||||
|
||||
List<Link> links = preparePersonResources(new Person("Frodo", "Baggins"), //
|
||||
new Person("Bilbo", "Baggins"), //
|
||||
new Person("Merry", "Baggins"), //
|
||||
new Person("Pippin", "Baggins"));
|
||||
|
||||
Link frodosSiblingLink = links.get(0);
|
||||
|
||||
patchAndGet(frodosSiblingLink, toUriList(links.get(1), links.get(2), links.get(3)), TEXT_URI_LIST);
|
||||
|
||||
assertSiblingNames(frodosSiblingLink, "Bilbo", "Merry", "Pippin");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-219
|
||||
*/
|
||||
@Test
|
||||
public void manipulatePropertyCollectionRestfullyWithMultiplePuts() throws Exception {
|
||||
|
||||
List<Link> links = preparePersonResources(new Person("Frodo", "Baggins"), //
|
||||
new Person("Bilbo", "Baggins"), //
|
||||
new Person("Merry", "Baggins"), //
|
||||
new Person("Pippin", "Baggins"));
|
||||
|
||||
Link frodosSiblingsLink = links.get(0);
|
||||
|
||||
putAndGet(frodosSiblingsLink, links.get(1).expand().getHref(), TEXT_URI_LIST);
|
||||
putAndGet(frodosSiblingsLink, links.get(2).expand().getHref(), TEXT_URI_LIST);
|
||||
putAndGet(frodosSiblingsLink, links.get(3).expand().getHref(), TEXT_URI_LIST);
|
||||
assertSiblingNames(frodosSiblingsLink, "Pippin");
|
||||
|
||||
patchAndGet(frodosSiblingsLink, links.get(2).getHref(), TEXT_URI_LIST);
|
||||
assertSiblingNames(frodosSiblingsLink, "Merry", "Pippin");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-219
|
||||
*/
|
||||
@Test
|
||||
public void manipulatePropertyCollectionRestfullyWithSinglePut() throws Exception {
|
||||
|
||||
List<Link> links = preparePersonResources(new Person("Frodo", "Baggins"), //
|
||||
new Person("Bilbo", "Baggins"), //
|
||||
new Person("Merry", "Baggins"), //
|
||||
new Person("Pippin", "Baggins"));
|
||||
|
||||
Link frodoSiblingLink = links.get(0);
|
||||
|
||||
putAndGet(frodoSiblingLink, toUriList(links.get(1), links.get(2), links.get(3)), TEXT_URI_LIST);
|
||||
assertSiblingNames(frodoSiblingLink, "Bilbo", "Merry", "Pippin");
|
||||
|
||||
putAndGet(frodoSiblingLink, toUriList(links.get(3)), TEXT_URI_LIST);
|
||||
assertSiblingNames(frodoSiblingLink, "Pippin");
|
||||
|
||||
patchAndGet(frodoSiblingLink, toUriList(links.get(2)), TEXT_URI_LIST);
|
||||
assertSiblingNames(frodoSiblingLink, "Merry", "Pippin");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-219
|
||||
*/
|
||||
@Test
|
||||
public void manipulatePropertyCollectionRestfullyWithDelete() throws Exception {
|
||||
|
||||
List<Link> links = preparePersonResources(new Person("Frodo", "Baggins"), //
|
||||
new Person("Bilbo", "Baggins"), //
|
||||
new Person("Merry", "Baggins"), //
|
||||
new Person("Pippin", "Baggins"));
|
||||
|
||||
Link frodosSiblingsLink = links.get(0);
|
||||
|
||||
patchAndGet(frodosSiblingsLink, links.get(1).getHref(), TEXT_URI_LIST);
|
||||
patchAndGet(frodosSiblingsLink, links.get(2).getHref(), TEXT_URI_LIST);
|
||||
patchAndGet(frodosSiblingsLink, links.get(3).getHref(), TEXT_URI_LIST);
|
||||
|
||||
String pippinId = new UriTemplate("/people/{id}").match(links.get(3).getHref()).get("id");
|
||||
deleteAndVerify(new Link(frodosSiblingsLink.getHref() + "/" + pippinId));
|
||||
|
||||
assertSiblingNames(frodosSiblingsLink, "Bilbo", "Merry");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-50
|
||||
*/
|
||||
@Test
|
||||
public void propertiesCanHaveNulls() throws Exception {
|
||||
|
||||
Link peopleLink = client.discoverUnique("people");
|
||||
|
||||
Person frodo = new Person();
|
||||
frodo.setFirstName("Frodo");
|
||||
frodo.setLastName(null);
|
||||
|
||||
MockHttpServletResponse response = postAndGet(peopleLink, mapper.writeValueAsString(frodo),
|
||||
MediaType.APPLICATION_JSON);
|
||||
String responseBody = response.getContentAsString();
|
||||
|
||||
assertEquals(JsonPath.read(responseBody, "$.firstName"), "Frodo");
|
||||
assertNull(JsonPath.read(responseBody, "$.lastName"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-238
|
||||
*/
|
||||
@Test
|
||||
public void putShouldWorkDespiteExistingLinks() throws Exception {
|
||||
|
||||
Link peopleLink = client.discoverUnique("people");
|
||||
|
||||
Person frodo = new Person("Frodo", "Baggins");
|
||||
String frodoString = mapper.writeValueAsString(frodo);
|
||||
|
||||
MockHttpServletResponse createdPerson = postAndGet(peopleLink, frodoString, MediaType.APPLICATION_JSON);
|
||||
|
||||
Link frodoLink = client.assertHasLinkWithRel("self", createdPerson);
|
||||
assertJsonPathEquals("$.firstName", "Frodo", createdPerson);
|
||||
|
||||
String bilboWithFrodosLinks = createdPerson.getContentAsString().replace("Frodo", "Bilbo");
|
||||
|
||||
MockHttpServletResponse overwrittenResponse = putAndGet(frodoLink, bilboWithFrodosLinks,
|
||||
MediaType.APPLICATION_JSON);
|
||||
|
||||
client.assertHasLinkWithRel("self", overwrittenResponse);
|
||||
assertJsonPathEquals("$.firstName", "Bilbo", overwrittenResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-217
|
||||
*/
|
||||
@Test
|
||||
public void doesNotAllowGetToCollectionResourceIfFindAllIsNotExported() throws Exception {
|
||||
|
||||
Link link = client.discoverUnique("addresses");
|
||||
|
||||
mvc.perform(get(link.getHref())).//
|
||||
andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-217
|
||||
*/
|
||||
@Test
|
||||
public void doesNotAllowPostToCollectionResourceIfSaveIsNotExported() throws Exception {
|
||||
|
||||
Link link = client.discoverUnique("addresses");
|
||||
|
||||
mvc.perform(post(link.getHref()).content("{}").contentType(MediaType.APPLICATION_JSON)).//
|
||||
andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, that the server only returns the properties contained in the projection requested.
|
||||
*
|
||||
* @see OrderSummary
|
||||
* @see DATAREST-221
|
||||
*/
|
||||
@Test
|
||||
public void returnsProjectionIfRequested() throws Exception {
|
||||
|
||||
Link orders = client.discoverUnique("orders");
|
||||
|
||||
MockHttpServletResponse response = client.request(orders);
|
||||
Link orderLink = assertContentLinkWithRel("self", response, true).expand();
|
||||
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(orderLink.getHref());
|
||||
String uri = builder.queryParam("projection", "summary").build().toUriString();
|
||||
|
||||
response = mvc.perform(get(uri)). //
|
||||
andExpect(status().isOk()). //
|
||||
andExpect(jsonPath("$.price", is(2.5))).//
|
||||
andReturn().getResponse();
|
||||
|
||||
assertJsonPathDoesntExist("$.lineItems", response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-261
|
||||
*/
|
||||
@Test
|
||||
public void relProviderDetectsCustomizedMapping() {
|
||||
assertThat(relProvider.getCollectionResourceRelFor(Person.class), is("people"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-311
|
||||
*/
|
||||
@Test
|
||||
public void onlyLinksShouldAppearWhenExecuteSearchCompact() throws Exception {
|
||||
|
||||
Link peopleLink = client.discoverUnique("people");
|
||||
Person daenerys = new Person("Daenerys", "Targaryen");
|
||||
String daenerysString = mapper.writeValueAsString(daenerys);
|
||||
|
||||
MockHttpServletResponse createdPerson = postAndGet(peopleLink, daenerysString, MediaType.APPLICATION_JSON);
|
||||
Link daenerysLink = client.assertHasLinkWithRel("self", createdPerson);
|
||||
assertJsonPathEquals("$.firstName", "Daenerys", createdPerson);
|
||||
|
||||
Link searchLink = client.discoverUnique(peopleLink, "search");
|
||||
Link byFirstNameLink = client.discoverUnique(searchLink, "findFirstPersonByFirstName");
|
||||
|
||||
MockHttpServletResponse response = client.request(byFirstNameLink.expand("Daenerys"),
|
||||
MediaType.parseMediaType("application/x-spring-data-compact+json"));
|
||||
|
||||
String responseBody = response.getContentAsString();
|
||||
|
||||
JSONArray personLinks = JsonPath.<JSONArray> read(responseBody, "$.links[?(@.rel=='person')].href");
|
||||
|
||||
assertThat(personLinks, hasSize(1));
|
||||
assertThat(personLinks.get(0), is((Object) daenerysLink.getHref()));
|
||||
assertThat(JsonPath.<JSONArray> read(responseBody, "$.content"), hasSize(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-317
|
||||
*/
|
||||
@Test
|
||||
public void rendersExcerptProjectionsCorrectly() throws Exception {
|
||||
|
||||
Link authorsLink = client.discoverUnique("authors");
|
||||
|
||||
MockHttpServletResponse response = client.request(authorsLink);
|
||||
String firstAuthorPath = "$._embedded.authors[0]";
|
||||
|
||||
// Has main content
|
||||
assertHasJsonPathValue(firstAuthorPath.concat(".name"), response);
|
||||
|
||||
// Embeddes content of related entity, self link and keeps relation link
|
||||
assertHasJsonPathValue(firstAuthorPath.concat("._embedded.books[0].title"), response);
|
||||
assertHasJsonPathValue(firstAuthorPath.concat("._embedded.books[0]._links.self"), response);
|
||||
assertHasJsonPathValue(firstAuthorPath.concat("._links.books"), response);
|
||||
|
||||
// Access item resource and expect link to related resource present
|
||||
String content = response.getContentAsString();
|
||||
String href = JsonPath.read(content, firstAuthorPath.concat("._links.self.href"));
|
||||
|
||||
client.follow(new Link(href)).andExpect(client.hasLinkWithRel("books"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-353
|
||||
*/
|
||||
@Test
|
||||
public void returns404WhenTryingToDeleteANonExistingResource() throws Exception {
|
||||
|
||||
Link receiptsLink = client.discoverUnique("receipts");
|
||||
|
||||
mvc.perform(delete(receiptsLink.getHref().concat("/{id}"), 4711)).//
|
||||
andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-384
|
||||
*/
|
||||
@Test
|
||||
public void execturesSearchThatTakesASort() throws Exception {
|
||||
|
||||
Link booksLink = client.discoverUnique("books");
|
||||
Link searchLink = client.discoverUnique(booksLink, "search");
|
||||
Link findBySortedLink = client.discoverUnique(searchLink, "find-by-sorted");
|
||||
|
||||
// Assert sort options advertised
|
||||
assertThat(findBySortedLink.isTemplated(), is(true));
|
||||
assertThat(findBySortedLink.getVariableNames(), hasItems("sort", "projection"));
|
||||
|
||||
// Assert results returned as specified
|
||||
client.follow(findBySortedLink.expand("title,desc")).//
|
||||
andExpect(jsonPath("$._embedded.books[0].title").value("Spring Data (Second Edition)")).//
|
||||
andExpect(jsonPath("$._embedded.books[1].title").value("Spring Data")).//
|
||||
andExpect(client.hasLinkWithRel("self"));
|
||||
|
||||
client.follow(findBySortedLink.expand("title,asc")).//
|
||||
andExpect(jsonPath("$._embedded.books[0].title").value("Spring Data")).//
|
||||
andExpect(jsonPath("$._embedded.books[1].title").value("Spring Data (Second Edition)")).//
|
||||
andExpect(client.hasLinkWithRel("self"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-160
|
||||
*/
|
||||
@Test
|
||||
public void returnConflictWhenConcurrentlyEditingVersionedEntity() throws Exception {
|
||||
|
||||
Link receiptLink = client.discoverUnique("receipts");
|
||||
|
||||
Receipt receipt = new Receipt();
|
||||
receipt.setAmount(new BigDecimal(50));
|
||||
receipt.setSaleItem("Springy Tacos");
|
||||
|
||||
String stringReceipt = mapper.writeValueAsString(receipt);
|
||||
|
||||
MockHttpServletResponse createdReceipt = postAndGet(receiptLink, stringReceipt, MediaType.APPLICATION_JSON);
|
||||
Link tacosLink = client.assertHasLinkWithRel("self", createdReceipt);
|
||||
assertJsonPathEquals("$.saleItem", "Springy Tacos", createdReceipt);
|
||||
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(tacosLink.getHref());
|
||||
String concurrencyTag = createdReceipt.getHeader("ETag");
|
||||
|
||||
mvc.perform(patch(builder.build().toUriString()).content("{ \"saleItem\" : \"SpringyBurritos\" }")
|
||||
.contentType(MediaType.APPLICATION_JSON).header(IF_MATCH, concurrencyTag))
|
||||
.andExpect(status().is2xxSuccessful());
|
||||
|
||||
mvc.perform(patch(builder.build().toUriString()).content("{ \"saleItem\" : \"SpringyTequila\" }")
|
||||
.contentType(MediaType.APPLICATION_JSON).header(IF_MATCH, "\"falseETag\""))
|
||||
.andExpect(status().isPreconditionFailed());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-423
|
||||
*/
|
||||
@Test
|
||||
public void invokesCustomControllerAndBindsDomainObjectCorrectly() throws Exception {
|
||||
|
||||
MockHttpServletResponse authorsResponse = client.request(client.discoverUnique("authors"));
|
||||
|
||||
String authorUri = JsonPath.read(authorsResponse.getContentAsString(), "$._embedded.authors[0]._links.self.href");
|
||||
|
||||
mvc.perform(delete(authorUri)).//
|
||||
andExpect(status().isIAmATeapot());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-523
|
||||
*/
|
||||
@Test
|
||||
public void augmentsCollectionAssociationUsingPost() throws Exception {
|
||||
|
||||
List<Link> links = preparePersonResources(new Person("Frodo", "Baggins"), //
|
||||
new Person("Bilbo", "Baggins"));
|
||||
|
||||
Link frodosSiblingsLink = links.get(0).expand();
|
||||
Link bilboLink = links.get(1);
|
||||
|
||||
for (int i = 1; i <= 2; i++) {
|
||||
|
||||
mvc.perform(post(frodosSiblingsLink.getHref()).//
|
||||
content(bilboLink.getHref()).//
|
||||
contentType(TEXT_URI_LIST)).//
|
||||
andExpect(status().isNoContent());
|
||||
|
||||
mvc.perform(get(frodosSiblingsLink.getHref())).//
|
||||
andExpect(jsonPath("$._embedded.people", hasSize(i)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-658
|
||||
*/
|
||||
@Test
|
||||
public void returnsLinkHeadersForHeadRequestToItemResource() throws Exception {
|
||||
|
||||
MockHttpServletResponse response = client.request(client.discoverUnique("people"));
|
||||
String personHref = JsonPath.read(response.getContentAsString(), "$._embedded.people[0]._links.self.href");
|
||||
|
||||
response = mvc.perform(head(personHref))//
|
||||
.andExpect(status().isNoContent())//
|
||||
.andReturn().getResponse();
|
||||
|
||||
Links links = Links.valueOf(response.getHeader("Link"));
|
||||
assertThat(links.hasLink("self"), is(true));
|
||||
assertThat(links.hasLink("person"), is(true));
|
||||
}
|
||||
|
||||
private List<Link> preparePersonResources(Person primary, Person... persons) throws Exception {
|
||||
|
||||
Link peopleLink = client.discoverUnique("people");
|
||||
List<Link> links = new ArrayList<Link>();
|
||||
|
||||
MockHttpServletResponse primaryResponse = postAndGet(peopleLink, mapper.writeValueAsString(primary),
|
||||
MediaType.APPLICATION_JSON);
|
||||
links.add(client.assertHasLinkWithRel("siblings", primaryResponse));
|
||||
|
||||
for (Person person : persons) {
|
||||
|
||||
String payload = mapper.writeValueAsString(person);
|
||||
MockHttpServletResponse response = postAndGet(peopleLink, payload, MediaType.APPLICATION_JSON);
|
||||
|
||||
links.add(client.assertHasLinkWithRel(Link.REL_SELF, response));
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the {@link Person} resource the given link points to contains siblings with the given names.
|
||||
*
|
||||
* @param link
|
||||
* @param siblingNames
|
||||
* @throws Exception
|
||||
*/
|
||||
private void assertSiblingNames(Link link, String... siblingNames) throws Exception {
|
||||
|
||||
String responseBody = client.request(link).getContentAsString();
|
||||
List<String> persons = JsonPath.read(responseBody, "$._embedded.people[*].firstName");
|
||||
|
||||
assertThat(persons, hasSize(siblingNames.length));
|
||||
assertThat(persons, hasItems(siblingNames));
|
||||
}
|
||||
|
||||
private void assertPersonWithNameAndSiblingLink(String name) throws Exception {
|
||||
|
||||
MockHttpServletResponse response = client.request(client.discoverUnique("people"));
|
||||
|
||||
String jsonPath = String.format("$._embedded.people[?(@.firstName == '%s')][0]", name);
|
||||
|
||||
// Assert content inlined
|
||||
Object john = JsonPath.read(response.getContentAsString(), jsonPath);
|
||||
assertThat(john, is(notNullValue()));
|
||||
assertThat(JsonPath.read(john, "$.firstName"), is(notNullValue()));
|
||||
|
||||
// Assert sibling link exposed in resource pointed to
|
||||
Link selfLink = new Link(JsonPath.<String> read(john, "$._links.self.href"));
|
||||
client.follow(selfLink).//
|
||||
andExpect(status().isOk()).//
|
||||
andExpect(jsonPath("$._links.siblings", is(notNullValue())));
|
||||
}
|
||||
|
||||
private static String toUriList(Link... links) {
|
||||
|
||||
List<String> uris = new ArrayList<String>(links.length);
|
||||
|
||||
for (Link link : links) {
|
||||
uris.add(link.expand().getHref());
|
||||
}
|
||||
|
||||
return StringUtils.collectionToDelimitedString(uris, "\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2015-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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.tests.TestMvcClient;
|
||||
import org.springframework.data.rest.webmvc.ProfileController;
|
||||
import org.springframework.data.rest.webmvc.ProfileResourceProcessor;
|
||||
import org.springframework.data.rest.webmvc.RestMediaTypes;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.LinkDiscoverers;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Series of tests to verify {@link ProfileController} serves ALPS and JSON Schema metadata from the root level and at
|
||||
* collection resource levels.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 2.4
|
||||
*/
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { JpaRepositoryConfig.class, ProfileIntegrationTests.Config.class })
|
||||
public class ProfileIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
@Autowired WebApplicationContext context;
|
||||
@Autowired LinkDiscoverers discoverers;
|
||||
|
||||
private static final String ROOT_URI = "/api";
|
||||
|
||||
@Configuration
|
||||
static class Config extends RepositoryRestConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
|
||||
config.setBasePath(ROOT_URI);
|
||||
}
|
||||
}
|
||||
|
||||
TestMvcClient client;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||
this.client = new TestMvcClient(mvc, this.discoverers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-230
|
||||
* @see DATAREST-638
|
||||
*/
|
||||
@Test
|
||||
public void exposesProfileLink() throws Exception {
|
||||
|
||||
client.follow(ROOT_URI)//
|
||||
.andExpect(status().is2xxSuccessful())//
|
||||
.andExpect(jsonPath("$._links.profile.href", endsWith(ProfileController.PROFILE_ROOT_MAPPING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-230
|
||||
* @see DATAREST-638
|
||||
*/
|
||||
@Test
|
||||
public void profileRootLinkContainsMetadataForEachRepo() throws Exception {
|
||||
|
||||
Link profileLink = client.discoverUnique(new Link(ROOT_URI), ProfileResourceProcessor.PROFILE_REL);
|
||||
|
||||
assertThat(client.discoverUnique(profileLink, "self", MediaType.ALL), is(notNullValue()));
|
||||
assertThat(client.discoverUnique(profileLink, "people", MediaType.ALL), is(notNullValue()));
|
||||
assertThat(client.discoverUnique(profileLink, "items", MediaType.ALL), is(notNullValue()));
|
||||
assertThat(client.discoverUnique(profileLink, "authors", MediaType.ALL), is(notNullValue()));
|
||||
assertThat(client.discoverUnique(profileLink, "books", MediaType.ALL), is(notNullValue()));
|
||||
assertThat(client.discoverUnique(profileLink, "orders", MediaType.ALL), is(notNullValue()));
|
||||
assertThat(client.discoverUnique(profileLink, "receipts", MediaType.ALL), is(notNullValue()));
|
||||
assertThat(client.discoverUnique(profileLink, "addresses", MediaType.ALL), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-638
|
||||
*/
|
||||
@Test
|
||||
public void profileLinkOnCollectionResourceLeadsToRepositorySpecificMetadata() throws Exception {
|
||||
|
||||
Link peopleLink = client.discoverUnique(new Link(ROOT_URI), "people");
|
||||
Link profileLink = client.discoverUnique(peopleLink, ProfileResourceProcessor.PROFILE_REL);
|
||||
|
||||
client.follow(profileLink, RestMediaTypes.ALPS_JSON).andExpect(status().is2xxSuccessful())
|
||||
.andExpect(header().string(HttpHeaders.CONTENT_TYPE, RestMediaTypes.ALPS_JSON_VALUE));
|
||||
|
||||
client.follow(profileLink, RestMediaTypes.SCHEMA_JSON).andExpect(status().is2xxSuccessful())
|
||||
.andExpect(header().string(HttpHeaders.CONTENT_TYPE, RestMediaTypes.SCHEMA_JSON_VALUE));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2013-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;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class TestDataPopulator {
|
||||
|
||||
@Autowired PersonRepository people;
|
||||
@Autowired OrderRepository orders;
|
||||
@Autowired AuthorRepository authors;
|
||||
@Autowired BookRepository books;
|
||||
|
||||
public void populateRepositories() {
|
||||
|
||||
books.deleteAll();
|
||||
authors.deleteAll();
|
||||
orders.deleteAll();
|
||||
people.deleteAll();
|
||||
|
||||
populatePeople();
|
||||
populateOrders();
|
||||
populateAuthorsAndBooks();
|
||||
}
|
||||
|
||||
private void populateAuthorsAndBooks() {
|
||||
|
||||
Author ollie = new Author("Ollie");
|
||||
Author mark = new Author("Mark");
|
||||
Author michael = new Author("Michael");
|
||||
Author david = new Author("David");
|
||||
Author john = new Author("John");
|
||||
Author thomas = new Author("Thomas");
|
||||
|
||||
Iterable<Author> authors = this.authors.save(Arrays.asList(ollie, mark, michael, david, john, thomas));
|
||||
|
||||
books.save(new Book("1449323952", "Spring Data", authors));
|
||||
books.save(new Book("1449323953", "Spring Data (Second Edition)", authors));
|
||||
}
|
||||
|
||||
private void populateOrders() {
|
||||
|
||||
Person person = people.findAll().iterator().next();
|
||||
|
||||
Order order = new Order(person);
|
||||
order.add(new LineItem("Java Chip"));
|
||||
orders.save(order);
|
||||
}
|
||||
|
||||
private void populatePeople() {
|
||||
|
||||
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,80 @@
|
||||
/*
|
||||
* 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 groovy.lang.GroovyObject;
|
||||
import groovy.lang.MetaClass;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* Simulates a Groovy domain object by extending {@link GroovyObject}.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Gierke
|
||||
* @see DATAREST-754
|
||||
*/
|
||||
@Entity
|
||||
public class SimulatedGroovyDomainClass implements GroovyObject {
|
||||
|
||||
private @Id @GeneratedValue 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;
|
||||
}
|
||||
|
||||
//
|
||||
// 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) {}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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;
|
||||
import org.springframework.data.rest.webmvc.jpa.groovy.SimulatedGroovyDomainClass;
|
||||
|
||||
/**
|
||||
* Simulates a repository built on a Groovy domain object.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @see DATAREST-754
|
||||
*/
|
||||
public interface SimulatedGroovyDomainClassRepository extends CrudRepository<SimulatedGroovyDomainClass, Long> {}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2015-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.json;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.data.rest.webmvc.jpa.Order;
|
||||
import org.springframework.data.rest.webmvc.jpa.OrderRepository;
|
||||
import org.springframework.data.rest.webmvc.jpa.Person;
|
||||
import org.springframework.data.rest.webmvc.jpa.PersonRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link Jackson2DatatypeHelper}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { JpaRepositoryConfig.class, RepositoryRestMvcConfiguration.class })
|
||||
@Transactional
|
||||
public class Jackson2DatatypeHelperIntegrationTests {
|
||||
|
||||
@Autowired PersistentEntities entities;
|
||||
@Autowired ObjectMapper objectMapper;
|
||||
|
||||
@Autowired PersonRepository people;
|
||||
@Autowired OrderRepository orders;
|
||||
@Autowired EntityManager em;
|
||||
|
||||
Order order;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
this.order = orders.save(new Order(people.save(new Person("Dave", "Matthews"))));
|
||||
|
||||
// Reset JPA to make sure the query returns a result with proxy references
|
||||
em.flush();
|
||||
em.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-500
|
||||
*/
|
||||
@Test
|
||||
public void configuresHIbernate4ModuleToLoadLazyLoadingProxies() throws Exception {
|
||||
|
||||
PersistentEntity<?, ?> entity = entities.getPersistentEntity(Order.class);
|
||||
PersistentProperty<?> property = entity.getPersistentProperty("creator");
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(orders.findOne(this.order.getId()));
|
||||
|
||||
assertThat(objectMapper.writeValueAsString(accessor.getProperty(property)), is(not("null")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.json;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
import org.springframework.context.support.StaticMessageSource;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.data.rest.webmvc.PersistentEntityResource;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.data.rest.webmvc.jpa.LineItem;
|
||||
import org.springframework.data.rest.webmvc.jpa.Order;
|
||||
import org.springframework.data.rest.webmvc.jpa.OrderRepository;
|
||||
import org.springframework.data.rest.webmvc.jpa.Person;
|
||||
import org.springframework.data.rest.webmvc.jpa.PersonRepository;
|
||||
import org.springframework.data.rest.webmvc.jpa.PersonSummary;
|
||||
import org.springframework.data.rest.webmvc.jpa.UserExcerpt;
|
||||
import org.springframework.data.rest.webmvc.util.TestUtils;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.LinkDiscoverer;
|
||||
import org.springframework.hateoas.PagedResources;
|
||||
import org.springframework.hateoas.PagedResources.PageMetadata;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.core.EmbeddedWrapper;
|
||||
import org.springframework.hateoas.core.EmbeddedWrappers;
|
||||
import org.springframework.hateoas.hal.HalLinkDiscoverer;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
/**
|
||||
* Integration tests for entity (de)serialization.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { JpaRepositoryConfig.class, PersistentEntitySerializationTests.TestConfig.class })
|
||||
@Transactional
|
||||
public class PersistentEntitySerializationTests {
|
||||
|
||||
private static final String PERSON_JSON_IN = "{\"firstName\": \"John\",\"lastName\": \"Doe\"}";
|
||||
|
||||
@Autowired ObjectMapper mapper;
|
||||
@Autowired Repositories repositories;
|
||||
@Autowired PersonRepository people;
|
||||
@Autowired OrderRepository orders;
|
||||
|
||||
@Configuration
|
||||
static class TestConfig extends RepositoryTestsConfig {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public ObjectMapper objectMapper() {
|
||||
|
||||
ObjectMapper objectMapper = super.objectMapper();
|
||||
objectMapper.registerModule(
|
||||
new JacksonSerializers(new EnumTranslator(new MessageSourceAccessor(new StaticMessageSource()))));
|
||||
return objectMapper;
|
||||
}
|
||||
}
|
||||
|
||||
LinkDiscoverer linkDiscoverer;
|
||||
ProjectionFactory projectionFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
RequestContextHolder.setRequestAttributes(new ServletWebRequest(new MockHttpServletRequest()));
|
||||
|
||||
this.linkDiscoverer = new HalLinkDiscoverer();
|
||||
this.projectionFactory = new SpelAwareProxyProjectionFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializesPersonEntity() throws IOException {
|
||||
|
||||
Person p = mapper.readValue(PERSON_JSON_IN, Person.class);
|
||||
|
||||
assertThat(p.getFirstName(), is("John"));
|
||||
assertThat(p.getLastName(), is("Doe"));
|
||||
assertThat(p.getSiblings(), is(Collections.EMPTY_LIST));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-238
|
||||
*/
|
||||
@Test
|
||||
public void deserializePersonWithLinks() throws IOException {
|
||||
|
||||
String bilbo = "{\n" + " \"_links\" : {\n" + " \"self\" : {\n"
|
||||
+ " \"href\" : \"http://localhost/people/4\"\n" + " },\n" + " \"siblings\" : {\n"
|
||||
+ " \"href\" : \"http://localhost/people/4/siblings\"\n" + " },\n" + " \"father\" : {\n"
|
||||
+ " \"href\" : \"http://localhost/people/4/father\"\n" + " }\n" + " },\n"
|
||||
+ " \"firstName\" : \"Bilbo\",\n" + " \"lastName\" : \"Baggins\",\n"
|
||||
+ " \"created\" : \"2014-01-31T21:07:45.574+0000\"\n" + "}\n";
|
||||
|
||||
Person p = mapper.readValue(bilbo, Person.class);
|
||||
assertThat(p.getFirstName(), equalTo("Bilbo"));
|
||||
assertThat(p.getLastName(), equalTo("Baggins"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-238
|
||||
*/
|
||||
@Test
|
||||
public void serializesPersonEntity() throws IOException, InterruptedException {
|
||||
|
||||
PersistentEntity<?, ?> persistentEntity = repositories.getPersistentEntity(Person.class);
|
||||
Person person = people.save(new Person("John", "Doe"));
|
||||
|
||||
PersistentEntityResource resource = PersistentEntityResource.build(person, persistentEntity).//
|
||||
withLink(new Link("/person/" + person.getId())).build();
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
mapper.writeValue(writer, resource);
|
||||
|
||||
String s = writer.toString();
|
||||
|
||||
Link fatherLink = linkDiscoverer.findLinkWithRel("father", s);
|
||||
assertThat(fatherLink.getHref(), endsWith(new UriTemplate("/{id}/father").expand(person.getId()).toString()));
|
||||
|
||||
Link siblingLink = linkDiscoverer.findLinkWithRel("siblings", s);
|
||||
assertThat(siblingLink.getHref(), endsWith(new UriTemplate("/{id}/siblings").expand(person.getId()).toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-248
|
||||
*/
|
||||
@Test
|
||||
public void deserializesPersonWithLinkToOtherPersonCorrectly() throws Exception {
|
||||
|
||||
Person father = people.save(new Person("John", "Doe"));
|
||||
|
||||
String child = String.format("{ \"firstName\" : \"Bilbo\", \"father\" : \"/persons/%s\"}", father.getId());
|
||||
Person result = mapper.readValue(child, Person.class);
|
||||
|
||||
assertThat(result.getFather(), is(father));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-248
|
||||
*/
|
||||
@Test
|
||||
public void deserializesPersonWithLinkToOtherPersonsCorrectly() throws Exception {
|
||||
|
||||
Person firstSibling = people.save(new Person("John", "Doe"));
|
||||
Person secondSibling = people.save(new Person("Dave", "Doe"));
|
||||
|
||||
String child = String.format("{ \"firstName\" : \"Bilbo\", \"siblings\" : [\"/persons/%s\", \"/persons/%s\"]}",
|
||||
firstSibling.getId(), secondSibling.getId());
|
||||
Person result = mapper.readValue(child, Person.class);
|
||||
|
||||
assertThat(result.getSiblings(), hasItems(firstSibling, secondSibling));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-248
|
||||
*/
|
||||
@Test
|
||||
public void deserializesEmbeddedAssociationsCorrectly() throws Exception {
|
||||
|
||||
String content = TestUtils.readFileFromClasspath("order.json");
|
||||
|
||||
Order order = mapper.readValue(content, Order.class);
|
||||
assertThat(order.getLineItems(), hasSize(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-250
|
||||
*/
|
||||
@Test
|
||||
public void serializesReferencesWithinPagedResourceCorrectly() throws Exception {
|
||||
|
||||
Person creator = new Person("Dave", "Matthews");
|
||||
|
||||
Order order = new Order(creator);
|
||||
order.add(new LineItem("first"));
|
||||
order.add(new LineItem("second"));
|
||||
|
||||
PersistentEntityResource orderResource = PersistentEntityResource.//
|
||||
build(order, repositories.getPersistentEntity(Order.class)).//
|
||||
withLink(new Link("/orders/1")).//
|
||||
build();
|
||||
|
||||
PagedResources<PersistentEntityResource> persistentEntityResource = new PagedResources<PersistentEntityResource>(
|
||||
Arrays.asList(orderResource), new PageMetadata(1, 0, 10));
|
||||
|
||||
String result = mapper.writeValueAsString(persistentEntityResource);
|
||||
|
||||
assertThat(JsonPath.read(result, "$_embedded.orders[*].lineItems"), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-521
|
||||
*/
|
||||
@Test
|
||||
public void serializesLinksForExcerpts() throws Exception {
|
||||
|
||||
Person dave = new Person("Dave", "Matthews");
|
||||
dave.setId(1L);
|
||||
|
||||
Person oliver = new Person("Oliver August", "Matthews");
|
||||
oliver.setId(2L);
|
||||
oliver.setFather(dave);
|
||||
|
||||
UserExcerpt daveExcerpt = projectionFactory.createProjection(UserExcerpt.class, dave);
|
||||
EmbeddedWrapper wrapper = new EmbeddedWrappers(false).wrap(daveExcerpt, "father");
|
||||
|
||||
PersistentEntityResource resource = PersistentEntityResource.//
|
||||
build(oliver, repositories.getPersistentEntity(Person.class)).//
|
||||
withEmbedded(Arrays.asList(wrapper)).//
|
||||
build();
|
||||
|
||||
String result = mapper.writeValueAsString(resource);
|
||||
|
||||
assertThat(JsonPath.read(result, "$_embedded.father[*]._links.self"), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-521
|
||||
*/
|
||||
@Test
|
||||
public void rendersAdditionalLinksRegisteredWithResource() throws Exception {
|
||||
|
||||
Person dave = new Person("Dave", "Matthews");
|
||||
|
||||
PersistentEntityResource resource = PersistentEntityResource.//
|
||||
build(dave, repositories.getPersistentEntity(Person.class)).//
|
||||
withLink(new Link("/people/1")).//
|
||||
withLink(new Link("/aditional", "processed")).//
|
||||
build();
|
||||
|
||||
String result = mapper.writeValueAsString(resource);
|
||||
|
||||
assertThat(JsonPath.read(result, "$_links.processed"), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-697
|
||||
*/
|
||||
@Test
|
||||
public void rendersProjectionWithinSimpleResourceCorrectly() throws Exception {
|
||||
|
||||
Person person = new Person("Dave", "Matthews");
|
||||
person.setId(1L);
|
||||
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
PersonSummary projection = factory.createProjection(PersonSummary.class, person);
|
||||
|
||||
String result = mapper.writeValueAsString(new Resource<PersonSummary>(projection));
|
||||
|
||||
assertThat(JsonPath.read(result, "$._links.self"), is(notNullValue()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.json;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.repository.support.DefaultRepositoryInvokerFactory;
|
||||
import org.springframework.data.repository.support.DomainClassConverter;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.data.rest.core.UriToEntityConverter;
|
||||
import org.springframework.data.rest.core.config.EnumTranslationConfiguration;
|
||||
import org.springframework.data.rest.core.config.MetadataConfiguration;
|
||||
import org.springframework.data.rest.core.config.ProjectionDefinitionConfiguration;
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.core.mapping.RepositoryResourceMappings;
|
||||
import org.springframework.data.rest.core.support.DefaultSelfLinkProvider;
|
||||
import org.springframework.data.rest.core.support.EntityLookup;
|
||||
import org.springframework.data.rest.core.support.SelfLinkProvider;
|
||||
import org.springframework.data.rest.webmvc.EmbeddedResourcesAssembler;
|
||||
import org.springframework.data.rest.webmvc.ResourceProcessorInvoker;
|
||||
import org.springframework.data.rest.webmvc.jpa.Person;
|
||||
import org.springframework.data.rest.webmvc.jpa.PersonRepository;
|
||||
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module.LookupObjectSerializer;
|
||||
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module.NestedEntitySerializer;
|
||||
import org.springframework.data.rest.webmvc.mapping.Associations;
|
||||
import org.springframework.data.rest.webmvc.mapping.LinkCollector;
|
||||
import org.springframework.data.rest.webmvc.spi.BackendIdConverter;
|
||||
import org.springframework.data.rest.webmvc.spi.BackendIdConverter.DefaultIdConverter;
|
||||
import org.springframework.data.rest.webmvc.support.ExcerptProjector;
|
||||
import org.springframework.data.rest.webmvc.support.PagingAndSortingTemplateVariables;
|
||||
import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.hateoas.EntityLinks;
|
||||
import org.springframework.hateoas.RelProvider;
|
||||
import org.springframework.hateoas.ResourceProcessor;
|
||||
import org.springframework.hateoas.core.EvoInflectorRelProvider;
|
||||
import org.springframework.hateoas.hal.Jackson2HalModule;
|
||||
import org.springframework.plugin.core.OrderAwarePluginRegistry;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin
|
||||
* @author Greg Turnquist
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
@SuppressWarnings("deprecation")
|
||||
public class RepositoryTestsConfig {
|
||||
|
||||
@Autowired ApplicationContext appCtx;
|
||||
@Autowired(required = false) List<MappingContext<?, ?>> mappingContexts = Collections.emptyList();
|
||||
|
||||
@Bean
|
||||
public Repositories repositories() {
|
||||
return new Repositories(appCtx);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RepositoryRestConfiguration config() {
|
||||
RepositoryRestConfiguration config = new RepositoryRestConfiguration(new ProjectionDefinitionConfiguration(),
|
||||
new MetadataConfiguration(), mock(EnumTranslationConfiguration.class));
|
||||
|
||||
config.setResourceMappingForDomainType(Person.class).setRel("person");
|
||||
|
||||
config.setResourceMappingForRepository(PersonRepository.class).setRel("people").setPath("people")
|
||||
.addResourceMappingFor("findByFirstName").setRel("firstname").setPath("firstname");
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultFormattingConversionService defaultConversionService() {
|
||||
|
||||
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
|
||||
|
||||
DomainClassConverter<FormattingConversionService> converter = new DomainClassConverter<FormattingConversionService>(
|
||||
conversionService);
|
||||
converter.setApplicationContext(appCtx);
|
||||
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistentEntities persistentEntities() {
|
||||
return new PersistentEntities(mappingContexts);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Module persistentEntityModule() {
|
||||
|
||||
RepositoryResourceMappings mappings = new RepositoryResourceMappings(repositories(), persistentEntities(),
|
||||
config().getRepositoryDetectionStrategy());
|
||||
EntityLinks entityLinks = new RepositoryEntityLinks(repositories(), mappings, config(),
|
||||
mock(PagingAndSortingTemplateVariables.class),
|
||||
OrderAwarePluginRegistry.<Class<?>, BackendIdConverter> create(Arrays.asList(DefaultIdConverter.INSTANCE)));
|
||||
SelfLinkProvider selfLinkProvider = new DefaultSelfLinkProvider(persistentEntities(), entityLinks,
|
||||
Collections.<EntityLookup<?>> emptyList());
|
||||
|
||||
DefaultRepositoryInvokerFactory invokerFactory = new DefaultRepositoryInvokerFactory(repositories());
|
||||
UriToEntityConverter uriToEntityConverter = new UriToEntityConverter(persistentEntities(), invokerFactory,
|
||||
repositories());
|
||||
|
||||
Associations associations = new Associations(mappings, config());
|
||||
LinkCollector collector = new LinkCollector(persistentEntities(), selfLinkProvider, associations);
|
||||
|
||||
NestedEntitySerializer nestedEntitySerializer = new NestedEntitySerializer(persistentEntities(),
|
||||
new EmbeddedResourcesAssembler(persistentEntities(), associations, mock(ExcerptProjector.class)),
|
||||
new ResourceProcessorInvoker(Collections.<ResourceProcessor<?>> emptyList()));
|
||||
|
||||
return new PersistentEntityJackson2Module(associations, persistentEntities(), uriToEntityConverter, collector,
|
||||
invokerFactory, nestedEntitySerializer, mock(LookupObjectSerializer.class));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ObjectMapper objectMapper() {
|
||||
|
||||
RelProvider relProvider = new EvoInflectorRelProvider();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
mapper.registerModule(new Jackson2HalModule());
|
||||
mapper.registerModule(persistentEntityModule());
|
||||
mapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, null, null));
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
mapper.setSerializationInclusion(Include.NON_EMPTY);
|
||||
|
||||
return mapper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link BackendIdHandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
public class BackendIdConverterHandlerMethodArgumentResolverIntegrationTests
|
||||
extends AbstractControllerIntegrationTests {
|
||||
|
||||
@Autowired BackendIdHandlerMethodArgumentResolver resolver;
|
||||
|
||||
/**
|
||||
* @see DATAREST-155
|
||||
*/
|
||||
@Test
|
||||
public void translatesUriToBackendId() throws Exception {
|
||||
|
||||
Method method = ReflectionUtils.findMethod(SampleController.class, "resolveId", Serializable.class);
|
||||
MethodParameter parameter = new MethodParameter(method, 0);
|
||||
NativeWebRequest request = new ServletWebRequest(new MockHttpServletRequest("GET", "/books/5-5-5-5-5"));
|
||||
|
||||
Object resolvedId = resolver.resolveArgument(parameter, null, request, null);
|
||||
|
||||
assertThat(resolvedId, is((Object) 5L));
|
||||
}
|
||||
|
||||
static class SampleController {
|
||||
|
||||
@RequestMapping("/{repository}/{id}")
|
||||
void resolveId(@BackendId Serializable backendId) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.support;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.rest.tests.AbstractWebIntegrationTests;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
/**
|
||||
* Integration tests for customization of Spring Data REST's exception handling.
|
||||
*
|
||||
* @author Thibaud Lepretre
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration
|
||||
public class ExceptionHandlingCustomizationIntegrationTests extends AbstractWebIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import(JpaRepositoryConfig.class)
|
||||
static class ControllerAdviceConfig {
|
||||
|
||||
@ControllerAdvice
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
static class CustomGlobalConfiguration {
|
||||
|
||||
@ExceptionHandler
|
||||
ResponseEntity<Void> handle(HttpRequestMethodNotSupportedException o_O) {
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAllow(o_O.getSupportedHttpMethods());
|
||||
|
||||
return new ResponseEntity<Void>(headers, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpRequestMethodNotSupportedExceptionShouldNowReturnHttpStatus500Over405() throws Exception {
|
||||
|
||||
Link link = client.discoverUnique("addresses");
|
||||
|
||||
mvc.perform(get(link.getHref())).//
|
||||
andExpect(status().isInternalServerError());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.support;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.tests.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.webmvc.jpa.Book;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.data.rest.webmvc.jpa.Order;
|
||||
import org.springframework.data.rest.webmvc.jpa.Person;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Links;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link RepositoryEntityLinks}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
public class RepositoryEntityLinksIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
@Autowired RepositoryRestConfiguration configuration;
|
||||
@Autowired RepositoryEntityLinks entityLinks;
|
||||
|
||||
@Test
|
||||
public void returnsLinkToSingleResource() {
|
||||
|
||||
Link link = entityLinks.linkToSingleResource(Person.class, 1);
|
||||
|
||||
assertThat(link.getHref(), endsWith("/people/1{?projection}"));
|
||||
assertThat(link.getRel(), is("person"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsTemplatedLinkForPagingResource() {
|
||||
|
||||
Link link = entityLinks.linkToCollectionResource(Person.class);
|
||||
|
||||
assertThat(link.isTemplated(), is(true));
|
||||
assertThat(link.getVariableNames(), hasItems("page", "size", "sort"));
|
||||
assertThat(link.getRel(), is("people"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-221
|
||||
*/
|
||||
@Test
|
||||
public void returnsLinkWithProjectionTemplateVariableIfProjectionIsDefined() {
|
||||
|
||||
Link link = entityLinks.linkToSingleResource(Order.class, 1);
|
||||
|
||||
assertThat(link.isTemplated(), is(true));
|
||||
assertThat(link.getVariableNames(), hasItem(configuration.getProjectionConfiguration().getParameterName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-155
|
||||
*/
|
||||
@Test
|
||||
public void usesCustomGeneratedBackendId() {
|
||||
|
||||
Link link = entityLinks.linkToSingleResource(Book.class, 7L);
|
||||
assertThat(link.expand().getHref(), endsWith("/7-7-7-7-7-7-7"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-317
|
||||
*/
|
||||
@Test
|
||||
public void adaptsToExistingPageable() {
|
||||
|
||||
Link link = entityLinks.linkToPagedResource(Person.class, new PageRequest(0, 10));
|
||||
|
||||
assertThat(link.isTemplated(), is(true));
|
||||
assertThat(link.getVariableNames(), hasSize(2));
|
||||
assertThat(link.getVariableNames(), hasItems("sort", "projection"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-467
|
||||
*/
|
||||
@Test
|
||||
public void returnsLinksToSearchResources() {
|
||||
|
||||
Links links = entityLinks.linksToSearchResources(Person.class);
|
||||
|
||||
assertThat(links.hasLink("firstname"), is(true));
|
||||
|
||||
Link firstnameLink = links.getLink("firstname");
|
||||
assertThat(firstnameLink.isTemplated(), is(true));
|
||||
assertThat(firstnameLink.getVariableNames(), hasItems("page", "size"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-467
|
||||
*/
|
||||
@Test
|
||||
public void returnsLinkToSearchResource() {
|
||||
|
||||
Link link = entityLinks.linkToSearchResource(Person.class, "firstname");
|
||||
|
||||
assertThat(link, is(notNullValue()));
|
||||
assertThat(link.isTemplated(), is(true));
|
||||
assertThat(link.getVariableNames(), hasItems("firstname", "page", "size"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-467
|
||||
* @see DATAREST-519
|
||||
*/
|
||||
@Test
|
||||
public void prepopulatesPaginationInformationForSearchResourceLink() {
|
||||
|
||||
Link link = entityLinks.linkToSearchResource(Person.class, "firstname", new PageRequest(0, 10));
|
||||
|
||||
assertThat(link, is(notNullValue()));
|
||||
assertThat(link.isTemplated(), is(true));
|
||||
assertThat(link.getVariableNames(), hasItem("firstname"));
|
||||
assertThat(link.getVariableNames(), not(hasItems("page", "size")));
|
||||
|
||||
UriComponents components = UriComponentsBuilder.fromUriString(link.getHref()).build();
|
||||
assertThat(components.getQueryParams(), allOf(hasKey("page"), hasKey("size")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-467
|
||||
*/
|
||||
@Test
|
||||
public void returnsTemplatedLinkForSortedSearchResource() {
|
||||
|
||||
Link link = entityLinks.linkToSearchResource(Person.class, "lastname");
|
||||
|
||||
assertThat(link.isTemplated(), is(true));
|
||||
assertThat(link.getVariableNames(), hasItems("lastname", "sort"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-467
|
||||
* @see DATAREST-519
|
||||
*/
|
||||
@Test
|
||||
public void prepopulatesSortInformationForSearchResourceLink() {
|
||||
|
||||
Link link = entityLinks.linkToSearchResource(Person.class, "lastname", new Sort("firstname"));
|
||||
|
||||
assertThat(link, is(notNullValue()));
|
||||
assertThat(link.isTemplated(), is(true));
|
||||
assertThat(link.getVariableNames(), hasItem("lastname"));
|
||||
assertThat(link.getVariableNames(), not(hasItems("sort")));
|
||||
|
||||
UriComponents components = UriComponentsBuilder.fromUriString(link.getHref()).build();
|
||||
assertThat(components.getQueryParams(), hasKey("sort"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-668
|
||||
* @see DATAREST-519
|
||||
* @see DATAREST-467
|
||||
*/
|
||||
@Test
|
||||
public void addsProjectVariableToSearchResourceIfAvailable() {
|
||||
|
||||
for (Link link : entityLinks.linksToSearchResources(Book.class)) {
|
||||
assertThat(link.getVariableNames(), hasItem("projection"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.util;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaWebTests;
|
||||
|
||||
/**
|
||||
* Test helper methods.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class TestUtils {
|
||||
|
||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
public static String readFileFromClasspath(String name) throws Exception {
|
||||
|
||||
ClassPathResource file = new ClassPathResource(name, JpaWebTests.class);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
Scanner scanner = new Scanner(file.getFile(), UTF8.name());
|
||||
|
||||
try {
|
||||
|
||||
while (scanner.hasNextLine()) {
|
||||
builder.append(scanner.nextLine());
|
||||
}
|
||||
|
||||
} finally {
|
||||
scanner.close();
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "http://localhost:8080/persons/1"
|
||||
}
|
||||
},
|
||||
"lineItems": [
|
||||
{
|
||||
"name": "Java Chip"
|
||||
},
|
||||
{
|
||||
"name": "Chocolate Mocca "
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{ "firstName" : "Dave",
|
||||
"lastName" : "Matthews"
|
||||
}
|
||||
Reference in New Issue
Block a user