This commit is contained in:
Jonathan Cook
2019-10-23 15:01:44 +02:00
parent db85c8f275
commit 684ec0d2e3
20486 changed files with 1642483 additions and 0 deletions
@@ -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 BooksApiApplication {
public static void main(String[] args) {
SpringApplication.run(BooksApiApplication.class, args);
}
}
@@ -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 {
}
@@ -0,0 +1,13 @@
package org.baeldung.persistence.dao;
import org.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);
}
@@ -0,0 +1,111 @@
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 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();
}
}
@@ -0,0 +1,9 @@
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
@@ -0,0 +1,13 @@
<?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>
@@ -0,0 +1,43 @@
package org.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;
}
}
}
@@ -0,0 +1,154 @@
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.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");
}
}
@@ -0,0 +1,67 @@
package org.baeldung;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
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());
}
}
@@ -0,0 +1,21 @@
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;
/**
*
* 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() {
}
}
@@ -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