JAVA-12465: Look into spring-cloud-rest module (#12406)
* JAVA-12465: Look into spring-cloud-rest module * JAVA-12465: updated README to include ebook reference
This commit is contained in:
parent
1ee4a09b2e
commit
77c668f340
|
@ -22,8 +22,7 @@
|
|||
<module>spring-cloud-eureka</module>
|
||||
<module>spring-cloud-hystrix</module>
|
||||
<module>spring-cloud-bootstrap</module>
|
||||
<module>spring-cloud-ribbon-client</module>
|
||||
<module>spring-cloud-rest</module>
|
||||
<module>spring-cloud-ribbon-client</module>
|
||||
<module>spring-cloud-zookeeper</module>
|
||||
<module>spring-cloud-gateway</module>
|
||||
<module>spring-cloud-stream</module>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## Spring Cloud Bootstrap
|
||||
## Guide to Microservices: with Spring Boot and Spring Cloud Ebook
|
||||
|
||||
This module contains articles about bootstrapping Spring Cloud applications
|
||||
This module contains articles about bootstrapping Spring Cloud applications that are part of the Guide to Microservices: with Spring Boot and Spring Cloud Ebook.
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
|
@ -1,5 +0,0 @@
|
|||
## Spring Cloud REST
|
||||
|
||||
This module contains articles about RESTful APIs with Spring Cloud
|
||||
|
||||
Code for an ebook - "A REST API with Spring Boot and Spring Cloud"
|
|
@ -1,16 +0,0 @@
|
|||
spring.application.name=discovery
|
||||
server.port=8761
|
||||
|
||||
#### cloud
|
||||
eureka.instance.hostname=localhost
|
||||
eureka.client.serviceUrl.defaultZone=${EUREKA_URI:http://system:systemPass@localhost:8761/eureka}
|
||||
eureka.client.registerWithEureka=false
|
||||
eureka.client.fetchRegistry=false
|
||||
|
||||
#### security
|
||||
security.basic.enabled=true
|
||||
security.basic.path=/**
|
||||
security.user.name=system
|
||||
security.user.password=systemPass
|
||||
security.user.role=ADMIN
|
||||
security.sessions=always
|
|
@ -1,20 +0,0 @@
|
|||
spring.application.name=resource
|
||||
#server.port=0
|
||||
|
||||
#### cloud
|
||||
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
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.spring.cloud</groupId>
|
||||
<artifactId>spring-cloud-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-cloud-rest-config-server</module>
|
||||
<module>spring-cloud-rest-discovery-server</module>
|
||||
<module>spring-cloud-rest-books-api</module>
|
||||
<module>spring-cloud-rest-reviews-api</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<spring-boot-maven-plugin.version>1.4.2.RELEASE</spring-boot-maven-plugin.version>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,78 +0,0 @@
|
|||
<?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>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest-books-api</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest-books-api</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Simple books API</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-1</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../../parent-boot-1</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>${junit-jupiter.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>Camden.SR4</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-config</artifactId>
|
||||
</dependency>
|
||||
<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>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -1,14 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableEurekaClient
|
||||
public class BooksApiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BooksApiApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.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 {
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package com.baeldung.persistence.dao;
|
||||
|
||||
import com.baeldung.persistence.model.Book;
|
||||
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 = "books", path = "books")
|
||||
public interface BookRepository extends CrudRepository<Book, Long> {
|
||||
Page<Book> findByTitle(@Param("title") String title, Pageable pageable);
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
package com.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 Book {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String title;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String author;
|
||||
|
||||
//
|
||||
|
||||
public Book() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Book(String title, String author) {
|
||||
super();
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = (prime * result) + ((author == null) ? 0 : author.hashCode());
|
||||
result = (prime * result) + (int) (id ^ (id >>> 32));
|
||||
result = (prime * result) + ((title == null) ? 0 : title.hashCode());
|
||||
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 Book other = (Book) obj;
|
||||
if (author == null) {
|
||||
if (other.author != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!author.equals(other.author)) {
|
||||
return false;
|
||||
}
|
||||
if (id != other.id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (title == null) {
|
||||
if (other.title != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!title.equals(other.title)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Book [id=").append(id).append(", title=").append(title).append(", author=").append(author).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
spring.cloud.config.name=resource
|
||||
spring.cloud.config.discovery.service-id=config
|
||||
spring.cloud.config.discovery.enabled=true
|
||||
spring.cloud.config.username=configUser
|
||||
spring.cloud.config.password=configPassword
|
||||
|
||||
eureka.client.serviceUrl.defaultZone=http://system:systemPass@localhost:8761/eureka
|
||||
|
||||
server.port=8084
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -1,43 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class BooksApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("unchecked")
|
||||
public RedisSerializer<Object> defaultRedisSerializer() {
|
||||
return Mockito.mock(RedisSerializer.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
|
||||
RedisConnectionFactory factory = Mockito.mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = Mockito.mock(RedisConnection.class);
|
||||
Mockito.when(factory.getConnection()).thenReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
package com.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 com.baeldung.BooksApiApplication;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
|
||||
import com.baeldung.persistence.model.Book;
|
||||
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 = { BooksApiApplication.class }, webEnvironment = WebEnvironment.DEFINED_PORT)
|
||||
public class RestApiLiveTest {
|
||||
|
||||
private static final String API_URI = "http://localhost:8084/books";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
RestAssured.authentication = preemptive().basic("user", "userPass");
|
||||
}
|
||||
|
||||
// GET
|
||||
|
||||
@Test
|
||||
public void whenGetAllBooks_thenOK() {
|
||||
final Response response = RestAssured.get(API_URI);
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetCreatedBookById_thenOK() {
|
||||
final Book book = createRandomBook();
|
||||
final String location = createBookAsUri(book);
|
||||
|
||||
final Response response = RestAssured.get(location);
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
assertEquals(book.getTitle(), response.jsonPath().get("title"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetCreatedBookByName_thenOK() {
|
||||
final Book book = createRandomBook();
|
||||
createBookAsUri(book);
|
||||
|
||||
final Response response = RestAssured.get(API_URI + "/search/findByTitle?title=" + book.getTitle());
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
assertTrue(response.jsonPath().getLong("page.totalElements") > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetNotExistBookById_thenNotFound() {
|
||||
final Response response = RestAssured.get(API_URI + "/" + randomNumeric(4));
|
||||
assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetNotExistBookByName_thenNotFound() {
|
||||
final Response response = RestAssured.get(API_URI + "/search/findByTitle?title=" + randomAlphabetic(20));
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
assertTrue(response.jsonPath().getLong("page.totalElements") == 0);
|
||||
}
|
||||
|
||||
// POST
|
||||
@Test
|
||||
public void whenCreateNewBook_thenCreated() {
|
||||
final Book book = createRandomBook();
|
||||
|
||||
final Response response = RestAssured.given().contentType(MediaType.APPLICATION_JSON_VALUE).body(book).post(API_URI);
|
||||
assertEquals(HttpStatus.CREATED.value(), response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCreateDuplicateBook_thenError() {
|
||||
final Book book = createRandomBook();
|
||||
createBookAsUri(book);
|
||||
|
||||
// duplicate
|
||||
final Response response = RestAssured.given().contentType(MediaType.APPLICATION_JSON_VALUE).body(book).post(API_URI);
|
||||
assertEquals(HttpStatus.CONFLICT.value(), response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInvalidBook_thenError() {
|
||||
final Book book = createRandomBook();
|
||||
book.setAuthor(null);
|
||||
|
||||
final Response response = RestAssured.given().contentType(MediaType.APPLICATION_JSON_VALUE).body(book).post(API_URI);
|
||||
assertEquals(HttpStatus.CONFLICT.value(), response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUpdateCreatedBook_thenUpdated() {
|
||||
// create
|
||||
final Book book = createRandomBook();
|
||||
final String location = createBookAsUri(book);
|
||||
|
||||
// update
|
||||
book.setAuthor("newAuthor");
|
||||
Response response = RestAssured.given().contentType(MediaType.APPLICATION_JSON_VALUE).body(book).put(location);
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
|
||||
// check if changes saved
|
||||
response = RestAssured.get(location);
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
assertEquals("newAuthor", response.jsonPath().get("author"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeleteCreatedBook_thenOk() {
|
||||
// create
|
||||
final Book book = createRandomBook();
|
||||
final String location = createBookAsUri(book);
|
||||
|
||||
// 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 whenDeleteNotExistBook_thenError() {
|
||||
final Response response = RestAssured.delete(API_URI + "/" + randomNumeric(4));
|
||||
assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatusCode());
|
||||
}
|
||||
|
||||
// =============================== Util
|
||||
|
||||
private Book createRandomBook() {
|
||||
final Book book = new Book();
|
||||
book.setTitle(randomAlphabetic(10));
|
||||
book.setAuthor(randomAlphabetic(15));
|
||||
return book;
|
||||
}
|
||||
|
||||
private String createBookAsUri(Book book) {
|
||||
final Response response = RestAssured.given().contentType(MediaType.APPLICATION_JSON_VALUE).body(book).post(API_URI);
|
||||
return response.jsonPath().get("_links.self.href");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.baeldung.BooksApiApplication;
|
||||
import com.baeldung.SessionConfig;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
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.test.context.junit4.SpringRunner;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = { BooksApiApplication.class, SessionConfig.class }, webEnvironment = WebEnvironment.DEFINED_PORT)
|
||||
public class SessionLiveTest {
|
||||
|
||||
private Jedis jedis;
|
||||
private static final String API_URI = "http://localhost:8084/books";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
jedis = new Jedis("localhost", 6379);
|
||||
jedis.flushAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenStart_thenNoSessionsExist() {
|
||||
final Set<String> result = jedis.keys("*");
|
||||
assertEquals(0, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnauthorizeUser_whenAccessResources_then_unAuthorized() {
|
||||
final Response response = RestAssured.get(API_URI);
|
||||
assertEquals(HttpStatus.UNAUTHORIZED.value(), response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAuthorizedUser_whenDeleteSession_thenUnauthorized() {
|
||||
// authorize User
|
||||
Response response = RestAssured.given().auth().preemptive().basic("user", "userPass").get(API_URI);
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
final String sessionCookie = response.getCookie("SESSION");
|
||||
|
||||
// check redis
|
||||
final Set<String> redisResult = jedis.keys("*");
|
||||
assertTrue(redisResult.size() > 0);
|
||||
|
||||
// login with cookie
|
||||
response = RestAssured.given().cookie("SESSION", sessionCookie).get(API_URI);
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
|
||||
// empty redis
|
||||
jedis.flushAll();
|
||||
|
||||
// login with cookie again
|
||||
response = RestAssured.given().cookie("SESSION", sessionCookie).get(API_URI);
|
||||
assertEquals(HttpStatus.UNAUTHORIZED.value(), response.getStatusCode());
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import com.baeldung.BooksApiApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
*
|
||||
* This Live Test requires:
|
||||
* * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = BooksApiApplication.class)
|
||||
public class SpringContextLiveTest {
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#### 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
|
|
@ -1,24 +0,0 @@
|
|||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
|
@ -1,58 +0,0 @@
|
|||
<?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>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest-config-server</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest-config-server</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Spring Cloud REST configuration server</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-1</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../../parent-boot-1</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>${junit-jupiter.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-eureka</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring-cloud.version>Camden.SR4</spring-cloud.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,17 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.config.server.EnableConfigServer;
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigServer
|
||||
@EnableEurekaClient
|
||||
public class SpringCloudRestConfigApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringCloudRestConfigApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
server.port=8081
|
||||
spring.application.name=config
|
||||
|
||||
spring.cloud.config.server.git.uri=${HOME}/application-config
|
||||
|
||||
eureka.client.region = default
|
||||
eureka.client.registryFetchIntervalSeconds = 5
|
||||
eureka.client.serviceUrl.defaultZone=${EUREKA_URI:http://system:systemPass@localhost:8761/eureka}
|
||||
|
||||
security.user.name=configUser
|
||||
security.user.password=configPassword
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -1,15 +0,0 @@
|
|||
package com.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(classes = SpringCloudRestConfigApplication.class)
|
||||
public class SpringContextTest {
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
|
@ -1,66 +0,0 @@
|
|||
<?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>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest-discovery-server</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest-discovery-server</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Spring Cloud REST server</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-1</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../../parent-boot-1</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>${junit-jupiter.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-eureka-server</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>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring-cloud.version>Edgware.SR4</spring-cloud.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,8 +0,0 @@
|
|||
package com.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 {
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableEurekaServer
|
||||
public class SpringCloudRestServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringCloudRestServerApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
spring.cloud.config.name=discovery
|
||||
spring.cloud.config.uri=http://localhost:8081
|
||||
spring.cloud.config.username=configUser
|
||||
spring.cloud.config.password=configPassword
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -1,42 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class SpringCloudRestServerIntegrationTest {
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("unchecked")
|
||||
public RedisSerializer<Object> defaultRedisSerializer() {
|
||||
return Mockito.mock(RedisSerializer.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
|
||||
RedisConnectionFactory factory = Mockito.mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = Mockito.mock(RedisConnection.class);
|
||||
Mockito.when(factory.getConnection()).thenReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
*
|
||||
* This Live Test requires:
|
||||
* * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = SpringCloudRestServerApplication.class)
|
||||
public class SpringContextLiveTest {
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
<?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>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest-reviews-api</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest-reviews-api</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Simple reviews API</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-1</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../../parent-boot-1</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>${junit-jupiter.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>Camden.SR4</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-config</artifactId>
|
||||
</dependency>
|
||||
<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>com.github.kstyrc</groupId>
|
||||
<artifactId>embedded-redis</artifactId>
|
||||
<version>${embedded-redis.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<rest-assured.version>3.0.1</rest-assured.version>
|
||||
<embedded-redis.version>0.6</embedded-redis.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,14 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableEurekaClient
|
||||
public class BookReviewsApiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BookReviewsApiApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.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 {
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package com.baeldung.persistence.dao;
|
||||
|
||||
import com.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);
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
package com.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();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
spring.cloud.config.name=resource
|
||||
spring.cloud.config.discovery.service-id=config
|
||||
spring.cloud.config.discovery.enabled=true
|
||||
spring.cloud.config.username=configUser
|
||||
spring.cloud.config.password=configPassword
|
||||
|
||||
eureka.client.serviceUrl.defaultZone=http://system:systemPass@localhost:8761/eureka
|
||||
|
||||
server.port=8085
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -1,43 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class BookReviewsApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
@EnableRedisHttpSession
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("unchecked")
|
||||
public RedisSerializer<Object> defaultRedisSerializer() {
|
||||
return Mockito.mock(RedisSerializer.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
|
||||
RedisConnectionFactory factory = Mockito.mock(RedisConnectionFactory.class);
|
||||
RedisConnection connection = Mockito.mock(RedisConnection.class);
|
||||
Mockito.when(factory.getConnection()).thenReturn(connection);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
package com.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 com.baeldung.BookReviewsApiApplication;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
|
||||
import com.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 = { BookReviewsApiApplication.class }, webEnvironment = WebEnvironment.DEFINED_PORT)
|
||||
public class RestApiLiveTest {
|
||||
|
||||
private static final String API_URI = "http://localhost:8085/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 whenGetCreatedReviewByBookId_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 whenGetNotExistReviewByBookId_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 whenCreateInvalidReview_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");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import com.baeldung.BookReviewsApiApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
*
|
||||
* This Live Test requires:
|
||||
* * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = BookReviewsApiApplication.class)
|
||||
public class SpringContextLiveTest {
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#### cloud
|
||||
spring.application.name=spring-cloud-eureka-client
|
||||
server.port=8085
|
||||
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
|
Loading…
Reference in New Issue