add book reviews service

This commit is contained in:
DOHA 2017-01-24 11:06:08 +02:00
parent e4bc0a44ce
commit ec121c1ade
20 changed files with 489 additions and 2 deletions

View File

@ -8,7 +8,8 @@
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>spring-cloud-rest-server</module>
<module>spring-cloud-rest-client</module>
<module>spring-cloud-rest-client-1</module>
<module>spring-cloud-rest-client-2</module>
</modules>
<packaging>pom</packaging>

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.baeldung</groupId>
<artifactId>spring-cloud-rest-client</artifactId>
<artifactId>spring-cloud-rest-client-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.baeldung</groupId>
<artifactId>spring-cloud-rest-client-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-cloud-rest</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<rest-assured.version>3.0.1</rest-assured.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*LiveTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,8 @@
package org.baeldung;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
}

View File

@ -0,0 +1,14 @@
package org.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class SpringCloudRestClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudRestClientApplication.class, args);
}
}

View File

@ -0,0 +1,13 @@
package org.baeldung.persistence.dao;
import org.baeldung.persistence.model.BookReview;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource(collectionResourceRel = "reviews", path = "reviews")
public interface BookReviewRepository extends CrudRepository<BookReview, Long> {
Page<BookReview> findByBookId(@Param("bookId") long bookId, Pageable pageable);
}

View File

@ -0,0 +1,128 @@
package org.baeldung.persistence.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class BookReview {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String content;
private int rating;
@Column(nullable = false)
private Long bookId;
//
public BookReview() {
super();
}
public BookReview(String content, int rating, long bookId) {
super();
this.content = content;
this.rating = rating;
this.bookId = bookId;
}
//
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
//
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + (int) (bookId ^ (bookId >>> 32));
result = (prime * result) + ((content == null) ? 0 : content.hashCode());
result = (prime * result) + (int) (id ^ (id >>> 32));
result = (prime * result) + rating;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final BookReview other = (BookReview) obj;
if (bookId != other.bookId) {
return false;
}
if (content == null) {
if (other.content != null) {
return false;
}
} else if (!content.equals(other.content)) {
return false;
}
if (id != other.id) {
return false;
}
if (rating != other.rating) {
return false;
}
return true;
}
//
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("BookReview [id=")
.append(id)
.append(", content=")
.append(content)
.append(", rating=")
.append(rating)
.append(", bookId=")
.append(bookId)
.append("]");
return builder.toString();
}
}

View File

@ -0,0 +1,19 @@
#### cloud
spring.application.name=spring-cloud-eureka-client
server.port=0
eureka.client.serviceUrl.defaultZone=${EUREKA_URI:http://system:systemPass@localhost:8761/eureka}
eureka.instance.preferIpAddress=true
#### persistence
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:cloud_rest;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
#### security
security.basic.enabled=true
security.basic.path=/**
security.user.name=user
security.user.password=userPass
security.user.role=USER
security.sessions=always

View File

@ -0,0 +1,162 @@
package org.baeldung;
import static io.restassured.RestAssured.preemptive;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.baeldung.persistence.model.BookReview;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SpringCloudRestClientApplication.class }, webEnvironment = WebEnvironment.DEFINED_PORT)
public class RestApiLiveTest {
private static final String API_URI = "http://localhost:8084/reviews";
@Before
public void setUp() {
RestAssured.authentication = preemptive().basic("user", "userPass");
}
// GET
@Test
public void whenGetAllReviews_thenOK() {
final Response response = RestAssured.get(API_URI);
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
}
@Test
public void whenGetCreatedReviewById_thenOK() {
final BookReview review = createRandomReview();
final String location = createReviewAsUri(review);
final Response response = RestAssured.get(location);
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
assertEquals(review.getContent(), response.jsonPath()
.get("content"));
}
@Test
public void whenGetCreatedReviewByName_thenOK() {
final BookReview review = createRandomReview();
createReviewAsUri(review);
final Response response = RestAssured.get(API_URI + "/search/findByBookId?bookId=" + review.getBookId());
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
assertTrue(response.jsonPath()
.getLong("page.totalElements") > 0);
}
@Test
public void whenGetNotExistReviewById_thenNotFound() {
final Response response = RestAssured.get(API_URI + "/" + randomNumeric(4));
assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatusCode());
}
@Test
public void whenGetNotExistReviewByName_thenNotFound() {
final Response response = RestAssured.get(API_URI + "/search/findByBookId?bookId=" + randomNumeric(4));
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
assertTrue(response.jsonPath()
.getLong("page.totalElements") == 0);
}
// POST
@Test
public void whenCreateNewReview_thenCreated() {
final BookReview review = createRandomReview();
final Response response = RestAssured.given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(review)
.post(API_URI);
assertEquals(HttpStatus.CREATED.value(), response.getStatusCode());
}
@Test
public void whenInvalidReview_thenError() {
final BookReview review = createRandomReview();
review.setBookId(null);
final Response response = RestAssured.given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(review)
.post(API_URI);
assertEquals(HttpStatus.CONFLICT.value(), response.getStatusCode());
}
@Test
public void whenUpdateCreatedReview_thenUpdated() {
// create
final BookReview review = createRandomReview();
final String location = createReviewAsUri(review);
// update
review.setRating(4);
Response response = RestAssured.given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(review)
.put(location);
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
// check if changes saved
response = RestAssured.get(location);
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
assertEquals(4, response.jsonPath()
.getInt("rating"));
}
@Test
public void whenDeleteCreatedReview_thenOk() {
// create
final BookReview review = createRandomReview();
final String location = createReviewAsUri(review);
// delete
Response response = RestAssured.delete(location);
assertEquals(HttpStatus.NO_CONTENT.value(), response.getStatusCode());
// confirm it was deleted
response = RestAssured.get(location);
assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatusCode());
}
@Test
public void whenDeleteNotExistReview_thenError() {
final Response response = RestAssured.delete(API_URI + "/" + randomNumeric(4));
assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatusCode());
}
// =============================== Util
private BookReview createRandomReview() {
final BookReview review = new BookReview();
review.setContent(randomAlphabetic(10));
review.setRating(3);
review.setBookId(1L);
return review;
}
private String createReviewAsUri(BookReview review) {
final Response response = RestAssured.given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(review)
.post(API_URI);
return response.jsonPath()
.get("_links.self.href");
}
}

View File

@ -0,0 +1,16 @@
package org.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringCloudRestClientApplicationTests {
@Test
public void contextLoads() {
}
}

View File

@ -0,0 +1,19 @@
#### cloud
spring.application.name=spring-cloud-eureka-client
server.port=8084
eureka.client.serviceUrl.defaultZone=${EUREKA_URI:http://system:systemPass@localhost:8761/eureka}
eureka.instance.preferIpAddress=true
#### persistence
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:cloud_rest;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
#### security
security.basic.enabled=true
security.basic.path=/**
security.user.name=user
security.user.password=userPass
security.user.role=USER
security.sessions=always