Merge remote-tracking branch 'upstream/master' into tutorials/binaryTreeJava
This commit is contained in:
commit
1fa5e1a8e3
|
@ -0,0 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [CAS SSO With Spring Security](http://www.baeldung.com/spring-security-cas-sso)
|
|
@ -32,3 +32,4 @@
|
|||
- [“Stream has already been operated upon or closed” Exception in Java](http://www.baeldung.com/java-stream-operated-upon-or-closed-exception)
|
||||
- [Display All Time Zones With GMT And UTC in Java](http://www.baeldung.com/java-time-zones)
|
||||
- [Copy a File with Java](http://www.baeldung.com/java-copy-file)
|
||||
- [Generating Prime Numbers in Java](http://www.baeldung.com/java-generate-prime-numbers)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package com.baeldung.stream;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
class PrimitiveStreams {
|
||||
|
||||
int min(int[] integers) {
|
||||
return Arrays.stream(integers).min().getAsInt();
|
||||
}
|
||||
|
||||
int max(int... integers) {
|
||||
return IntStream.of(integers).max().getAsInt();
|
||||
}
|
||||
|
||||
int sum(int... integers) {
|
||||
return IntStream.of(integers).sum();
|
||||
}
|
||||
|
||||
double avg(int... integers) {
|
||||
return IntStream.of(integers).average().getAsDouble();
|
||||
}
|
||||
}
|
|
@ -38,23 +38,14 @@ public class CounterUtil {
|
|||
|
||||
public static void counterWithMutableInteger(Map<String, MutableInteger> counterMap) {
|
||||
for (String country : COUNTRY_NAMES) {
|
||||
MutableInteger oldValue = counterMap.get(country);
|
||||
if (oldValue != null) {
|
||||
oldValue.increment();
|
||||
} else {
|
||||
counterMap.put(country, new MutableInteger(1));
|
||||
}
|
||||
counterMap.compute(country, (k, v) -> v == null ? new MutableInteger(0) : v)
|
||||
.increment();
|
||||
}
|
||||
}
|
||||
|
||||
public static void counterWithPrimitiveArray(Map<String, int[]> counterMap) {
|
||||
for (String country : COUNTRY_NAMES) {
|
||||
int[] oldCounter = counterMap.get(country);
|
||||
if (oldCounter != null) {
|
||||
oldCounter[0] += 1;
|
||||
} else {
|
||||
counterMap.put(country, new int[] { 1 });
|
||||
}
|
||||
counterMap.compute(country, (k, v) -> v == null ? new int[] { 0 } : v)[0]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package com.baeldung.stream;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PrimitiveStreamsUnitTest {
|
||||
|
||||
private PrimitiveStreams streams = new PrimitiveStreams();
|
||||
|
||||
@Test
|
||||
public void givenAnArrayOfIntegersWhenMinIsCalledThenCorrectMinIsReturned() {
|
||||
int[] integers = new int[] {20, 98, 12, 7, 35};
|
||||
int min = streams.min(integers); // returns 7
|
||||
|
||||
assertEquals(7, min);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAnArrayOfIntegersWhenMaxIsCalledThenCorrectMaxIsReturned() {
|
||||
int max = streams.max(20, 98, 12, 7, 35);
|
||||
|
||||
assertEquals(98, max);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAnArrayOfIntegersWhenSumIsCalledThenCorrectSumIsReturned() {
|
||||
int sum = streams.sum(20, 98, 12, 7, 35);
|
||||
|
||||
assertEquals(172, sum);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAnArrayOfIntegersWhenAvgIsCalledThenCorrectAvgIsReturned() {
|
||||
double avg = streams.avg(20, 98, 12, 7, 35);
|
||||
|
||||
assertTrue(34.4 == avg);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenARangeOfIntegersWhenIntStreamSumIsCalledThenCorrectSumIsReturned() {
|
||||
int sum = IntStream.range(1, 10).sum();
|
||||
|
||||
assertEquals(45, sum);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenARangeClosedOfIntegersWhenIntStreamSumIsCalledThenCorrectSumIsReturned() {
|
||||
int sum = IntStream.rangeClosed(1, 10).sum();
|
||||
|
||||
assertEquals(55, sum);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenARangeWhenForEachIsCalledThenTheIndicesWillBePrinted() {
|
||||
IntStream.rangeClosed(1, 5).parallel().forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAnArrayWhenSumIsCalledThenTheCorrectSumIsReturned() {
|
||||
|
||||
int sum = Arrays.asList(33,45).stream().mapToInt(a -> a).sum();
|
||||
|
||||
assertEquals(78, sum);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAnIntStreamThenGetTheEvenIntegers() {
|
||||
List<Integer> evenInts = IntStream.rangeClosed(1, 10)
|
||||
.filter(i -> i % 2 == 0)
|
||||
.boxed()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Integer> expected = IntStream.of(2, 4, 6, 8, 10).boxed().collect(Collectors.toList());
|
||||
|
||||
assertEquals(expected, evenInts);
|
||||
}
|
||||
|
||||
class Person {
|
||||
private int age;
|
||||
|
||||
Person(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
int getAge() {
|
||||
return age;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,3 +18,4 @@
|
|||
- [How to Get All Dates Between Two Dates?](http://www.baeldung.com/java-between-dates)
|
||||
- [Java 9 java.util.Objects Additions](http://www.baeldung.com/java-9-objects-new)
|
||||
- [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string)
|
||||
- [Convert Date to LocalDate or LocalDateTime and Back](http://www.baeldung.com/java-date-to-localdate-and-localdatetime)
|
||||
|
|
|
@ -31,3 +31,5 @@
|
|||
- [Overview of the java.util.concurrent](http://www.baeldung.com/java-util-concurrent)
|
||||
- [Semaphores in Java](http://www.baeldung.com/java-semaphore)
|
||||
- [Daemon Threads in Java](http://www.baeldung.com/java-daemon-thread)
|
||||
- [Implementing a Runnable vs Extending a Thread](http://www.baeldung.com/java-runnable-vs-extending-thread)
|
||||
- [How to Kill a Java Thread](http://www.baeldung.com/java-thread-stop)
|
||||
|
|
|
@ -10,9 +10,9 @@ import java.util.concurrent.*;
|
|||
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
|
||||
public class WaitingForThreadsToFinishTest {
|
||||
public class WaitingForThreadsToFinishManualTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WaitingForThreadsToFinishTest.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WaitingForThreadsToFinishManualTest.class);
|
||||
private final static ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10);
|
||||
|
||||
public void awaitTerminationAfterShutdown(ExecutorService threadPool) {
|
||||
|
@ -142,66 +142,4 @@ public class WaitingForThreadsToFinishTest {
|
|||
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMultipleThreads_whenUsingCompletableFutures_thenMainThreadShouldWaitForAllToFinish() {
|
||||
|
||||
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "Hello";
|
||||
});
|
||||
|
||||
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "Beautiful";
|
||||
});
|
||||
|
||||
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "World";
|
||||
});
|
||||
|
||||
long startProcessingTime = System.currentTimeMillis();
|
||||
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2, future3);
|
||||
combinedFuture.join();
|
||||
|
||||
long totalProcessingTime = System.currentTimeMillis() - startProcessingTime;
|
||||
assertTrue(totalProcessingTime >= 5000 && totalProcessingTime < 6000);
|
||||
|
||||
LOG.debug("Responses from all threads are available after " + totalProcessingTime + " milliseconds");
|
||||
|
||||
try {
|
||||
String thread1Response = future1.get();
|
||||
assertTrue(thread1Response.equals("Hello"));
|
||||
|
||||
String thread2Response = future2.get();
|
||||
assertTrue(thread2Response.equals("Beautiful"));
|
||||
|
||||
String thread3Response = future3.get();
|
||||
assertTrue(thread3Response.equals("World"));
|
||||
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);
|
||||
}
|
||||
}
|
|
@ -121,4 +121,8 @@
|
|||
- [Copy a File with Java](http://www.baeldung.com/java-copy-file)
|
||||
- [Introduction to Creational Design Patterns](http://www.baeldung.com/creational-design-patterns)
|
||||
- [Quick Example - Comparator vs Comparable in Java](http://www.baeldung.com/java-comparator-comparable)
|
||||
|
||||
- [Quick Guide to Java Stack](http://www.baeldung.com/java-stack)
|
||||
- [The Java continue and break Keywords](http://www.baeldung.com/java-continue-and-break)
|
||||
- [Java – Append Data to a File](http://www.baeldung.com/java-append-to-file)
|
||||
- [Introduction to the Java ArrayDeque](http://www.baeldung.com/java-array-deque)
|
||||
- [Guide to java.util.Formatter](http://www.baeldung.com/java-string-formatter)
|
||||
|
|
|
@ -5,12 +5,12 @@ import org.openjdk.jmh.annotations.*;
|
|||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SearchArrayTest {
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Warmup(iterations = 5)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
public class SearchArrayTest {
|
||||
|
||||
@Benchmark
|
||||
public void searchArrayLoop() {
|
||||
|
||||
int count = 1000;
|
||||
|
@ -21,9 +21,6 @@ public class SearchArrayTest {
|
|||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Warmup(iterations = 5)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
public void searchArrayAllocNewList() {
|
||||
|
||||
int count = 1000;
|
||||
|
@ -35,9 +32,6 @@ public class SearchArrayTest {
|
|||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Warmup(iterations = 5)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
public void searchArrayAllocNewSet() {
|
||||
|
||||
int count = 1000;
|
||||
|
@ -49,9 +43,6 @@ public class SearchArrayTest {
|
|||
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Warmup(iterations = 5)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
public void searchArrayReuseList() {
|
||||
|
||||
int count = 1000;
|
||||
|
@ -66,9 +57,6 @@ public class SearchArrayTest {
|
|||
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Warmup(iterations = 5)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
public void searchArrayReuseSet() {
|
||||
|
||||
int count = 1000;
|
||||
|
@ -81,9 +69,6 @@ public class SearchArrayTest {
|
|||
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Warmup(iterations = 5)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
public void searchArrayBinarySearch() {
|
||||
|
||||
int count = 1000;
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.baeldung.interfaces;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CommaSeparatedCustomers implements Customer.List {
|
||||
|
||||
private List<Customer> customers = new ArrayList<Customer>();
|
||||
|
||||
@Override
|
||||
public void Add(Customer customer) {
|
||||
customers.add(customer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomerNames() {
|
||||
return customers.stream().map(customer -> customer.getName()).collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.interfaces;
|
||||
|
||||
public class Customer {
|
||||
public interface List {
|
||||
void Add(Customer customer);
|
||||
|
||||
String getCustomerNames();
|
||||
}
|
||||
|
||||
private String name;
|
||||
|
||||
public Customer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ public class GenericFile {
|
|||
}
|
||||
|
||||
public String getFileInfo() {
|
||||
return String.format("File Name: %s\n" + " Extension: %s\n" + " Date Created: %s\n" + " Version: %s\n", this.getName(), this.getExtension(), this.getDateCreated(), this.getVersion());
|
||||
return "Generic File Impl";
|
||||
}
|
||||
|
||||
public Object read() {
|
||||
|
|
|
@ -30,7 +30,7 @@ public class ImageFile extends GenericFile {
|
|||
}
|
||||
|
||||
public String getFileInfo() {
|
||||
return String.format(" %s Height: %d\n Width: %d", super.getFileInfo(), this.getHeight(), this.getWidth());
|
||||
return "Image File Impl";
|
||||
}
|
||||
|
||||
public String read() {
|
||||
|
|
|
@ -21,7 +21,7 @@ public class TextFile extends GenericFile {
|
|||
}
|
||||
|
||||
public String getFileInfo() {
|
||||
return String.format(" %s Word Count: %d", super.getFileInfo(), wordCount);
|
||||
return "Text File Impl";
|
||||
}
|
||||
|
||||
public String read() {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.interfaces;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class InnerInterfaceTests {
|
||||
@Test
|
||||
public void whenCustomerListJoined_thenReturnsJoinedNames() {
|
||||
Customer.List customerList = new CommaSeparatedCustomers();
|
||||
customerList.Add(new Customer("customer1"));
|
||||
customerList.Add(new Customer("customer2"));
|
||||
assertEquals("customer1,customer2", customerList.getCustomerNames());
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
### Relevant Articles:
|
||||
- [Introduction to Drools](http://www.baeldung.com/drools)
|
||||
- [Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel)
|
||||
- [An Example of Backward Chaining in Drools](http://www.baeldung.com/drools-backward-chaining)
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
<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>
|
||||
<artifactId>flyway</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>flyway</name>
|
||||
<packaging>pom</packaging>
|
||||
<description>A sample project to demonstrate Flyway migrations</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-flyway</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-maven-plugin</artifactId>
|
||||
<version>${flyway-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<mysql.version>6.0.5</mysql.version>
|
||||
<flyway-maven-plugin.version>4.0.3</flyway-maven-plugin.version>
|
||||
<spring.boot.version>1.5.8.RELEASE</spring.boot.version>
|
||||
</properties>
|
||||
</project>
|
|
@ -1,57 +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>
|
||||
|
||||
<artifactId>spring-flyway</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-flyway</name>
|
||||
<description>Spring Boot Test Flyway Migrations</description>
|
||||
|
||||
<parent>
|
||||
<artifactId>flyway</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0</version>
|
||||
<relativePath>../../flyway</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -1,28 +0,0 @@
|
|||
package com.baeldung.springflyway.entities;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class Customer {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
private String email;
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package com.baeldung.springflyway.migration;
|
||||
|
||||
import org.flywaydb.core.api.migration.spring.SpringJdbcMigration;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
public class V2__uk_lastname_customer implements SpringJdbcMigration {
|
||||
|
||||
final String CUSTOMER_LASTNAME_UK = "ALTER TABLE customer ADD CONSTRAINT uk_customer_lastname UNIQUE(last_name);";
|
||||
|
||||
@Override
|
||||
public void migrate(final JdbcTemplate jdbcTemplate) throws Exception {
|
||||
jdbcTemplate.execute(CUSTOMER_LASTNAME_UK);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package com.baeldung.springflyway.repositories;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface CustomerRepository extends JpaRepository<Customer, Long> {
|
||||
|
||||
Optional<Customer> findByEmail(String email);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CustomerRepositoryInitialMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test
|
||||
public void givenSchemaCreationMigration_whenTryingToCreateACustomer_thenSuccess() {
|
||||
Customer customer = customerRepository.save(Customer
|
||||
.builder()
|
||||
.email("customer@email.com")
|
||||
.build());
|
||||
assertNotNull(customer.getId());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CustomerRepositoryInsertDataMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test
|
||||
public void givenASetInsertData_whenRunningMigrationsWithSuccess_thenASpecificCustomerIsFound() {
|
||||
Optional<Customer> customerOptional = customerRepository.findByEmail("email@email.com");
|
||||
assertTrue(customerOptional.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenASetInsertData_whenRunningMigrationsWithSuccess_thenASetOfCustomersIsFound() {
|
||||
List<Customer> customers = customerRepository.findAll();
|
||||
assertNotNull(customers);
|
||||
assertEquals(customers.size(), 6);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CustomerRepositoryNotNullConstraintMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
public void givenTheNotNullConstraintMigrations_whenInsertingACustomerWithNullEmail_thenThrowException() {
|
||||
customerRepository.save(Customer
|
||||
.builder()
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(properties = {
|
||||
"flyway.locations[0]=db/migration", "flyway.locations[1]=com/baeldung/springflyway/migration"
|
||||
})
|
||||
public class CustomerRepositoryUniqueConstraintJavaMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
public void givenTheUniqueConstraintMigrations_whenInsertingAnExistingLastNameCustomer_thenThrowException() {
|
||||
customerRepository.save(Customer
|
||||
.builder()
|
||||
.lastName("LastName")
|
||||
.build());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CustomerRepositoryUniqueConstraintMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
public void givenTheUniqueConstraintMigrations_whenInsertingAnExistingEmailCustomer_thenThrowException() {
|
||||
customerRepository.save(Customer
|
||||
.builder()
|
||||
.email("email@email.com")
|
||||
.build());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
spring.jpa.hibernate.ddl-auto=validate
|
|
@ -1,6 +0,0 @@
|
|||
create table if not exists customer (
|
||||
id bigint AUTO_INCREMENT not null primary key,
|
||||
first_name varchar(255) ,
|
||||
last_name varchar(255) ,
|
||||
email varchar(255)
|
||||
);
|
|
@ -1,6 +0,0 @@
|
|||
insert into customer (first_name, last_name, email) values ('FirstName', 'LastName', 'email@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName1', 'LastName1', 'email1@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName2', 'LastName2', 'email2@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName3', 'LastName3', 'email3@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName4', 'LastName4', 'email4@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName5', 'LastName5', 'email5@email.com');
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE customer ALTER email SET NOT NULL;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE customer ADD CONSTRAINT uk_customer_email UNIQUE(email);
|
|
@ -1 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [Introduction to Gradle](http://www.baeldung.com/gradle)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
repositories{
|
||||
mavenCentral()
|
||||
}
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: com.baeldung.GreetingPlugin
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
}
|
||||
|
||||
greeting {
|
||||
greeter = "Stranger"
|
||||
message = "Message from the build script!"
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
public class GreetingPlugin implements Plugin<Project> {
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
|
||||
GreetingPluginExtension extension = project.getExtensions().create("greeting", GreetingPluginExtension.class);
|
||||
|
||||
project.task("hello").doLast(task -> {
|
||||
System.out.println("Hello, " + extension.getGreeter());
|
||||
System.out.println("I have a message for You: " + extension.getMessage()); }
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.baeldung;
|
||||
|
||||
public class GreetingPluginExtension {
|
||||
private String greeter = "Baeldung";
|
||||
private String message = "Message from Plugin!";
|
||||
|
||||
public String getGreeter() {
|
||||
return greeter;
|
||||
}
|
||||
|
||||
public void setGreeter(String greeter) {
|
||||
this.greeter = greeter;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
|
@ -2,3 +2,5 @@
|
|||
|
||||
- [Dynamic Mapping with Hibernate](http://www.baeldung.com/hibernate-dynamic-mapping)
|
||||
- [An Overview of Identifiers in Hibernate](http://www.baeldung.com/hibernate-identifiers)
|
||||
- [Hibernate – Mapping Date and Time](http://www.baeldung.com/hibernate-date-time)
|
||||
- [Hibernate Inheritance Mapping](http://www.baeldung.com/hibernate-inheritance)
|
||||
|
|
|
@ -1,20 +1,7 @@
|
|||
BASIC CRUD API with Spring Boot
|
||||
================================
|
||||
|
||||
This is the code of a simple API for some CRUD operations realised for a seminar at [FGI](www.fgi-ud.org) using Spring Boot.
|
||||
|
||||
### Demo
|
||||
* API: The online version **is**/**will be** hosted here: https://fgi-tcheck.herokuapp.com
|
||||
* Mobile version is also opensource and located here: https://github.com/valdesekamdem/tcheck-mobile
|
||||
|
||||
### Features
|
||||
#### Currently Implemented
|
||||
* CRUD
|
||||
* Student
|
||||
|
||||
#### To DO
|
||||
* Validations of input with: [Spring Data Rest Validators](http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/validation-chapter.html)
|
||||
|
||||
This is the code of a simple API for some CRUD operations build using Spring Boot.
|
||||
|
||||
### Requirements
|
||||
|
||||
|
@ -49,7 +36,6 @@ Or create a new one via a POST:
|
|||
$ curl -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Dassi", "lastName" : "Orleando", "phoneNumber": "+237 545454545", "email": "mymail@yahoo.fr" }' localhost:8080/students
|
||||
```
|
||||
|
||||
|
||||
Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080)
|
||||
|
||||
Enjoy it :)
|
|
@ -0,0 +1,68 @@
|
|||
2017-12-13 04:50:16,291 INFO o.a.j.u.JMeterUtils: Setting Locale to en_US
|
||||
2017-12-13 04:50:16,319 INFO o.a.j.JMeter: Loading user properties from: /Users/dassiorleando/projects/biz/baeldung/jmeter/apache-jmeter-3.3/bin/user.properties
|
||||
2017-12-13 04:50:16,392 INFO o.a.j.JMeter: Loading system properties from: /Users/dassiorleando/projects/biz/baeldung/jmeter/apache-jmeter-3.3/bin/system.properties
|
||||
2017-12-13 04:50:16,406 INFO o.a.j.JMeter: Setting JMeter property: jmeter.save.saveservice.output_format=xml
|
||||
2017-12-13 04:50:16,451 INFO o.a.j.JMeter: Copyright (c) 1998-2017 The Apache Software Foundation
|
||||
2017-12-13 04:50:16,451 INFO o.a.j.JMeter: Version 3.3 r1808647
|
||||
2017-12-13 04:50:16,451 INFO o.a.j.JMeter: java.version=1.8.0_152
|
||||
2017-12-13 04:50:16,451 INFO o.a.j.JMeter: java.vm.name=Java HotSpot(TM) 64-Bit Server VM
|
||||
2017-12-13 04:50:16,451 INFO o.a.j.JMeter: os.name=Mac OS X
|
||||
2017-12-13 04:50:16,451 INFO o.a.j.JMeter: os.arch=x86_64
|
||||
2017-12-13 04:50:16,452 INFO o.a.j.JMeter: os.version=10.12.6
|
||||
2017-12-13 04:50:16,452 INFO o.a.j.JMeter: file.encoding=UTF-8
|
||||
2017-12-13 04:50:16,452 INFO o.a.j.JMeter: Max memory =536870912
|
||||
2017-12-13 04:50:16,452 INFO o.a.j.JMeter: Available Processors =4
|
||||
2017-12-13 04:50:16,461 INFO o.a.j.JMeter: Default Locale=English (United States)
|
||||
2017-12-13 04:50:16,462 INFO o.a.j.JMeter: JMeter Locale=English (United States)
|
||||
2017-12-13 04:50:16,462 INFO o.a.j.JMeter: JMeterHome=/Users/dassiorleando/projects/biz/baeldung/jmeter/apache-jmeter-3.3
|
||||
2017-12-13 04:50:16,462 INFO o.a.j.JMeter: user.dir =/Users/dassiorleando/projects/biz/baeldung/tutorials/jmeter
|
||||
2017-12-13 04:50:16,462 INFO o.a.j.JMeter: PWD =/Users/dassiorleando/projects/biz/baeldung/tutorials/jmeter
|
||||
2017-12-13 04:50:16,466 INFO o.a.j.JMeter: IP: 192.168.10.100 Name: MBP FullName: 192.168.10.100
|
||||
2017-12-13 04:50:16,472 INFO o.a.j.s.FileServer: Default base='/Users/dassiorleando/projects/biz/baeldung/tutorials/jmeter'
|
||||
2017-12-13 04:50:16,473 INFO o.a.j.s.FileServer: Set new base='/Users/dassiorleando/projects/biz/baeldung/tutorials/jmeter/src/main/resources'
|
||||
2017-12-13 04:50:17,022 INFO o.a.j.s.SaveService: Testplan (JMX) version: 2.2. Testlog (JTL) version: 2.2
|
||||
2017-12-13 04:50:17,134 INFO o.a.j.s.SaveService: Using SaveService properties file encoding UTF-8
|
||||
2017-12-13 04:50:17,142 INFO o.a.j.s.SaveService: Using SaveService properties version 3.2
|
||||
2017-12-13 04:50:17,168 INFO o.a.j.s.SaveService: Loading file: src/main/resources/JMeter.jmx
|
||||
2017-12-13 04:50:17,340 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for text/html is org.apache.jmeter.protocol.http.parser.LagartoBasedHtmlParser
|
||||
2017-12-13 04:50:17,351 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for application/xhtml+xml is org.apache.jmeter.protocol.http.parser.LagartoBasedHtmlParser
|
||||
2017-12-13 04:50:17,352 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for application/xml is org.apache.jmeter.protocol.http.parser.LagartoBasedHtmlParser
|
||||
2017-12-13 04:50:17,352 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for text/xml is org.apache.jmeter.protocol.http.parser.LagartoBasedHtmlParser
|
||||
2017-12-13 04:50:17,353 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for text/vnd.wap.wml is org.apache.jmeter.protocol.http.parser.RegexpHTMLParser
|
||||
2017-12-13 04:50:17,353 INFO o.a.j.p.h.s.HTTPSamplerBase: Parser for text/css is org.apache.jmeter.protocol.http.parser.CssParser
|
||||
2017-12-13 04:50:17,552 INFO o.a.j.JMeter: Creating summariser <summary>
|
||||
2017-12-13 04:50:17,580 INFO o.a.j.e.StandardJMeterEngine: Running the test!
|
||||
2017-12-13 04:50:17,581 INFO o.a.j.s.SampleEvent: List of sample_variables: []
|
||||
2017-12-13 04:50:17,582 INFO o.a.j.s.SampleEvent: List of sample_variables: []
|
||||
2017-12-13 04:50:17,590 INFO o.a.j.e.u.CompoundVariable: Note: Function class names must contain the string: '.functions.'
|
||||
2017-12-13 04:50:17,590 INFO o.a.j.e.u.CompoundVariable: Note: Function class names must not contain the string: '.gui.'
|
||||
2017-12-13 04:50:18,640 INFO o.a.j.JMeter: Running test (1513137018640)
|
||||
2017-12-13 04:50:18,728 INFO o.a.j.e.StandardJMeterEngine: Starting ThreadGroup: 1 : Thread Group
|
||||
2017-12-13 04:50:18,737 INFO o.a.j.e.StandardJMeterEngine: Starting 5 threads for group Thread Group.
|
||||
2017-12-13 04:50:18,737 INFO o.a.j.e.StandardJMeterEngine: Thread will continue on error
|
||||
2017-12-13 04:50:18,738 INFO o.a.j.t.ThreadGroup: Starting thread group... number=1 threads=5 ramp-up=1 perThread=200.0 delayedStart=false
|
||||
2017-12-13 04:50:18,751 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-1
|
||||
2017-12-13 04:50:18,753 INFO o.a.j.t.ThreadGroup: Started thread group number 1
|
||||
2017-12-13 04:50:18,753 INFO o.a.j.e.StandardJMeterEngine: All thread groups have been started
|
||||
2017-12-13 04:50:18,786 INFO o.a.j.p.h.s.HTTPHCAbstractImpl: Local host = MBP
|
||||
2017-12-13 04:50:18,797 INFO o.a.j.p.h.s.HTTPHC4Impl: HTTP request retry count = 0
|
||||
2017-12-13 04:50:18,812 INFO o.a.j.s.SampleResult: Note: Sample TimeStamps are START times
|
||||
2017-12-13 04:50:18,812 INFO o.a.j.s.SampleResult: sampleresult.default.encoding is set to ISO-8859-1
|
||||
2017-12-13 04:50:18,812 INFO o.a.j.s.SampleResult: sampleresult.useNanoTime=true
|
||||
2017-12-13 04:50:18,812 INFO o.a.j.s.SampleResult: sampleresult.nanoThreadSleep=5000
|
||||
2017-12-13 04:50:18,954 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-2
|
||||
2017-12-13 04:50:19,152 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-3
|
||||
2017-12-13 04:50:19,257 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-3
|
||||
2017-12-13 04:50:19,257 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-3
|
||||
2017-12-13 04:50:19,264 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-2
|
||||
2017-12-13 04:50:19,264 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-1
|
||||
2017-12-13 04:50:19,264 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-2
|
||||
2017-12-13 04:50:19,265 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-1
|
||||
2017-12-13 04:50:19,353 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-4
|
||||
2017-12-13 04:50:19,365 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-4
|
||||
2017-12-13 04:50:19,365 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-4
|
||||
2017-12-13 04:50:19,557 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-5
|
||||
2017-12-13 04:50:19,573 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-5
|
||||
2017-12-13 04:50:19,573 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-5
|
||||
2017-12-13 04:50:19,573 INFO o.a.j.e.StandardJMeterEngine: Notifying test listeners of end of test
|
||||
2017-12-13 04:50:19,575 INFO o.a.j.r.Summariser: summary = 5 in 00:00:01 = 5.4/s Avg: 155 Min: 10 Max: 388 Err: 4 (80.00%)
|
|
@ -0,0 +1,69 @@
|
|||
<?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>
|
||||
|
||||
<artifactId>jmeter</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>jmeter</name>
|
||||
<description>Intro to Performance testing using JMeter</description>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-boot-5</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-5</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<jmeter.version>2.6.0</jmeter.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</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-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.lazerycode.jmeter</groupId>
|
||||
<artifactId>jmeter-maven-plugin</artifactId>
|
||||
<version>${jmeter.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jmeter-tests</id>
|
||||
<goals>
|
||||
<goal>jmeter</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<testFilesDirectory>${project.basedir}/src/main/resources</testFilesDirectory>
|
||||
<resultsDirectory>${project.basedir}/src/main/resources</resultsDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,Latency,IdleTime,Connect
|
||||
1513134869133,1075,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-4,text,false,"The operation lasted too long: It took 1,075 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1075
|
||||
1513134869272,935,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-1,text,false,"The operation lasted too long: It took 935 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,935
|
||||
1513134869133,1075,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-3,text,false,"The operation lasted too long: It took 1,075 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1075
|
||||
1513134869272,935,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-2,text,false,"The operation lasted too long: It took 935 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,934
|
||||
1513134869133,1074,HTTP Request,Non HTTP response code: java.net.ConnectException,Non HTTP response message: Connection refused (Connection refused),Thread Group 1-5,text,false,"The operation lasted too long: It took 1,074 milliseconds, but should not have lasted longer than 10 milliseconds.",2058,0,5,5,0,0,1074
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="3.2" jmeter="3.3 r1808647">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="JMeter Jenkins" enabled="true">
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="JMeter" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testResults version="1.2">
|
||||
<httpSample t="83" it="0" lt="81" ct="1" ts="1513137019153" s="false" lb="HTTP Request" rc="200" rm="" tn="Thread Group 1-3" dt="text" by="502" sby="126" ng="3" na="3">
|
||||
<assertionResult>
|
||||
<name>Duration Assertion</name>
|
||||
<failure>true</failure>
|
||||
<error>false</error>
|
||||
<failureMessage>The operation lasted too long: It took 83 milliseconds, but should not have lasted longer than 10 milliseconds.</failureMessage>
|
||||
</assertionResult>
|
||||
</httpSample>
|
||||
<httpSample t="388" it="0" lt="382" ct="292" ts="1513137018851" s="false" lb="HTTP Request" rc="200" rm="" tn="Thread Group 1-1" dt="text" by="502" sby="126" ng="3" na="3">
|
||||
<assertionResult>
|
||||
<name>Duration Assertion</name>
|
||||
<failure>true</failure>
|
||||
<error>false</error>
|
||||
<failureMessage>The operation lasted too long: It took 388 milliseconds, but should not have lasted longer than 10 milliseconds.</failureMessage>
|
||||
</assertionResult>
|
||||
</httpSample>
|
||||
<httpSample t="281" it="0" lt="279" ct="189" ts="1513137018955" s="false" lb="HTTP Request" rc="200" rm="" tn="Thread Group 1-2" dt="text" by="502" sby="126" ng="3" na="3">
|
||||
<assertionResult>
|
||||
<name>Duration Assertion</name>
|
||||
<failure>true</failure>
|
||||
<error>false</error>
|
||||
<failureMessage>The operation lasted too long: It took 281 milliseconds, but should not have lasted longer than 10 milliseconds.</failureMessage>
|
||||
</assertionResult>
|
||||
</httpSample>
|
||||
<httpSample t="10" it="0" lt="10" ct="1" ts="1513137019354" s="true" lb="HTTP Request" rc="200" rm="" tn="Thread Group 1-4" dt="text" by="502" sby="126" ng="1" na="1">
|
||||
<assertionResult>
|
||||
<name>Duration Assertion</name>
|
||||
<failure>false</failure>
|
||||
<error>false</error>
|
||||
</assertionResult>
|
||||
</httpSample>
|
||||
<httpSample t="13" it="0" lt="13" ct="1" ts="1513137019558" s="false" lb="HTTP Request" rc="200" rm="" tn="Thread Group 1-5" dt="text" by="502" sby="126" ng="1" na="1">
|
||||
<assertionResult>
|
||||
<name>Duration Assertion</name>
|
||||
<failure>true</failure>
|
||||
<error>false</error>
|
||||
<failureMessage>The operation lasted too long: It took 13 milliseconds, but should not have lasted longer than 10 milliseconds.</failureMessage>
|
||||
</assertionResult>
|
||||
</httpSample>
|
||||
|
||||
</testResults>
|
|
@ -1 +1,4 @@
|
|||
## JSON B
|
||||
|
||||
## Relevant articles:
|
||||
- [Introduction to the JSON Binding API (JSR 367) in Java](http://www.baeldung.com/java-json-binding-api)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [The Order of Tests in JUnit](http://www.baeldung.com/junit-5-test-order)
|
|
@ -637,6 +637,23 @@
|
|||
<artifactId>google-http-client-gson</artifactId>
|
||||
<version>${googleclient.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- google api -->
|
||||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client</artifactId>
|
||||
<version>${google-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.oauth-client</groupId>
|
||||
<artifactId>google-oauth-client-jetty</artifactId>
|
||||
<version>${google-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.apis</groupId>
|
||||
<artifactId>google-api-services-sheets</artifactId>
|
||||
<version>${google-sheets.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
|
@ -710,5 +727,7 @@
|
|||
<cache.version>1.0.0</cache.version>
|
||||
<hazelcast.version>3.8.4</hazelcast.version>
|
||||
<caffeine.version>2.5.5</caffeine.version>
|
||||
<google-api.version>1.23.0</google-api.version>
|
||||
<google-sheets.version>v4-rev493-1.21.0</google-sheets.version>
|
||||
</properties>
|
||||
</project>
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.google.sheets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
|
||||
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
|
||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||
import com.google.api.client.util.store.MemoryDataStoreFactory;
|
||||
import com.google.api.services.sheets.v4.SheetsScopes;
|
||||
|
||||
public class GoogleAuthorizeUtil {
|
||||
public static Credential authorize() throws IOException, GeneralSecurityException {
|
||||
InputStream in = GoogleAuthorizeUtil.class.getResourceAsStream("/google-sheets-client-secret.json");
|
||||
GoogleClientSecrets clientSecrets = GoogleClientSecrets
|
||||
.load(JacksonFactory.getDefaultInstance(), new InputStreamReader(in));
|
||||
|
||||
List<String> scopes = Arrays.asList(SheetsScopes.SPREADSHEETS);
|
||||
|
||||
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow
|
||||
.Builder(GoogleNetHttpTransport.newTrustedTransport(),
|
||||
JacksonFactory.getDefaultInstance(),
|
||||
clientSecrets,
|
||||
scopes)
|
||||
.setDataStoreFactory(new MemoryDataStoreFactory())
|
||||
.setAccessType("offline")
|
||||
.build();
|
||||
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver())
|
||||
.authorize("user");
|
||||
|
||||
return credential;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.baeldung.google.sheets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||
import com.google.api.services.sheets.v4.Sheets;
|
||||
|
||||
public class SheetsServiceUtil {
|
||||
|
||||
private static final String APPLICATION_NAME = "Google Sheets Example";
|
||||
|
||||
public static Sheets getSheetsService() throws IOException, GeneralSecurityException {
|
||||
Credential credential = GoogleAuthorizeUtil.authorize();
|
||||
return new Sheets.Builder(GoogleNetHttpTransport.newTrustedTransport(),
|
||||
JacksonFactory.getDefaultInstance(), credential)
|
||||
.setApplicationName(APPLICATION_NAME)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{"installed":{"client_id":"394827218507-2ev02b2ha8plt7g2lh5nqse02ee737cf.apps.googleusercontent.com","project_id":"decisive-octane-187810","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"2MnN1DfenoCGWMay3v8Bf7eI","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
|
|
@ -0,0 +1,140 @@
|
|||
package com.baeldung.google.sheets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.api.services.sheets.v4.Sheets;
|
||||
import com.google.api.services.sheets.v4.model.AppendValuesResponse;
|
||||
import com.google.api.services.sheets.v4.model.BatchGetValuesResponse;
|
||||
import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetRequest;
|
||||
import com.google.api.services.sheets.v4.model.BatchUpdateValuesRequest;
|
||||
import com.google.api.services.sheets.v4.model.BatchUpdateValuesResponse;
|
||||
import com.google.api.services.sheets.v4.model.CopyPasteRequest;
|
||||
import com.google.api.services.sheets.v4.model.GridRange;
|
||||
import com.google.api.services.sheets.v4.model.Request;
|
||||
import com.google.api.services.sheets.v4.model.Spreadsheet;
|
||||
import com.google.api.services.sheets.v4.model.SpreadsheetProperties;
|
||||
import com.google.api.services.sheets.v4.model.UpdateSpreadsheetPropertiesRequest;
|
||||
import com.google.api.services.sheets.v4.model.UpdateValuesResponse;
|
||||
import com.google.api.services.sheets.v4.model.ValueRange;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
public class GoogleSheetsIntegrationTest {
|
||||
|
||||
private static Sheets sheetsService;
|
||||
|
||||
// this id can be replaced with your spreadsheet id
|
||||
// otherwise be advised that multiple people may run this test and update the public spreadsheet
|
||||
private static final String SPREADSHEET_ID = "1sILuxZUnyl_7-MlNThjt765oWshN3Xs-PPLfqYe4DhI";
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws GeneralSecurityException, IOException {
|
||||
sheetsService = SheetsServiceUtil.getSheetsService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWriteSheet_thenReadSheetOk() throws IOException {
|
||||
ValueRange body = new ValueRange()
|
||||
.setValues(Arrays.asList(
|
||||
Arrays.asList("Expenses January"),
|
||||
Arrays.asList("books", "30"),
|
||||
Arrays.asList("pens", "10"),
|
||||
Arrays.asList("Expenses February"),
|
||||
Arrays.asList("clothes", "20"),
|
||||
Arrays.asList("shoes", "5")));
|
||||
UpdateValuesResponse result = sheetsService.spreadsheets().values()
|
||||
.update(SPREADSHEET_ID, "A1", body)
|
||||
.setValueInputOption("RAW")
|
||||
.execute();
|
||||
|
||||
List<ValueRange> data = new ArrayList<>();
|
||||
data.add(new ValueRange()
|
||||
.setRange("D1")
|
||||
.setValues(Arrays.asList(
|
||||
Arrays.asList("January Total", "=B2+B3"))));
|
||||
data.add(new ValueRange()
|
||||
.setRange("D4")
|
||||
.setValues(Arrays.asList(
|
||||
Arrays.asList("February Total", "=B5+B6"))));
|
||||
|
||||
BatchUpdateValuesRequest batchBody = new BatchUpdateValuesRequest()
|
||||
.setValueInputOption("USER_ENTERED")
|
||||
.setData(data);
|
||||
BatchUpdateValuesResponse batchResult =
|
||||
sheetsService.spreadsheets().values()
|
||||
.batchUpdate(SPREADSHEET_ID, batchBody)
|
||||
.execute();
|
||||
|
||||
List<String> ranges = Arrays.asList("E1","E4");
|
||||
BatchGetValuesResponse readResult =
|
||||
sheetsService.spreadsheets().values()
|
||||
.batchGet(SPREADSHEET_ID)
|
||||
.setRanges(ranges)
|
||||
.execute();
|
||||
|
||||
ValueRange januaryTotal = readResult.getValueRanges().get(0);
|
||||
assertThat(januaryTotal.getValues().get(0).get(0)).isEqualTo("40");
|
||||
|
||||
ValueRange febTotal = readResult.getValueRanges().get(1);
|
||||
assertThat(febTotal.getValues().get(0).get(0)).isEqualTo("25");
|
||||
|
||||
ValueRange appendBody = new ValueRange()
|
||||
.setValues(Arrays.asList(
|
||||
Arrays.asList("Total", "=E1+E4")));
|
||||
AppendValuesResponse appendResult =
|
||||
sheetsService.spreadsheets().values()
|
||||
.append(SPREADSHEET_ID, "A1", appendBody)
|
||||
.setValueInputOption("USER_ENTERED")
|
||||
.setInsertDataOption("INSERT_ROWS")
|
||||
.setIncludeValuesInResponse(true)
|
||||
.execute();
|
||||
|
||||
ValueRange total = appendResult.getUpdates().getUpdatedData();
|
||||
assertThat(total.getValues().get(0).get(1)).isEqualTo("65");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenUpdateSpreadSheetTitle_thenOk() throws IOException {
|
||||
|
||||
UpdateSpreadsheetPropertiesRequest updateRequest = new UpdateSpreadsheetPropertiesRequest()
|
||||
.setFields("*")
|
||||
.setProperties(new SpreadsheetProperties().setTitle("Expenses"));
|
||||
|
||||
CopyPasteRequest copyRequest = new CopyPasteRequest()
|
||||
.setSource(new GridRange().setSheetId(0)
|
||||
.setStartColumnIndex(0).setEndColumnIndex(2)
|
||||
.setStartRowIndex(0).setEndRowIndex(1))
|
||||
.setDestination(new GridRange().setSheetId(1)
|
||||
.setStartColumnIndex(0).setEndColumnIndex(2)
|
||||
.setStartRowIndex(0).setEndRowIndex(1))
|
||||
.setPasteType("PASTE_VALUES");
|
||||
|
||||
List<Request> requests = new ArrayList<>();
|
||||
|
||||
requests.add(new Request().setCopyPaste(copyRequest));
|
||||
requests.add(new Request().setUpdateSpreadsheetProperties(updateRequest));
|
||||
|
||||
BatchUpdateSpreadsheetRequest body =
|
||||
new BatchUpdateSpreadsheetRequest().setRequests(requests);
|
||||
|
||||
sheetsService.spreadsheets().batchUpdate(SPREADSHEET_ID, body).execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCreateSpreadSheet_thenIdOk() throws IOException {
|
||||
Spreadsheet spreadSheet = new Spreadsheet()
|
||||
.setProperties(new SpreadsheetProperties().setTitle("My Spreadsheet"));
|
||||
Spreadsheet result = sheetsService.spreadsheets().create(spreadSheet).execute();
|
||||
|
||||
assertThat(result.getSpreadsheetId()).isNotNull();
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@ import org.neuroph.core.NeuralNetwork;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class XORTest {
|
||||
public class XORIntegrationTest {
|
||||
private NeuralNetwork ann = null;
|
||||
|
||||
private void print(String input, double output, double actual) {
|
|
@ -86,6 +86,9 @@ org.eclipse.osgi_3.12.1.v20170821-1548.jar
|
|||
|
||||
= = NOT GOOD = =
|
||||
|
||||
## Relevant articles:
|
||||
- [Introduction to OSGi](http://www.baeldung.com/osgi)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
###Relevant Articles:
|
||||
- [A Guide to the Front Controller Pattern in Java](http://www.baeldung.com/java-front-controller-pattern)
|
||||
- [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java)
|
||||
- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/template-method-pattern-in-java)
|
||||
- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
- [Deleting Objects with Hibernate](http://www.baeldung.com/delete-with-hibernate)
|
||||
- [Self-Contained Testing Using an In-Memory Database](http://www.baeldung.com/spring-jpa-test-in-memory-database)
|
||||
- [Spring Data JPA – Adding a Method in All Repositories](http://www.baeldung.com/spring-data-jpa-method-in-all-repositories)
|
||||
- [A Guide to Spring AbstractRoutingDatasource](http://www.baeldung.com/spring-abstract-routing-data-source)
|
||||
|
||||
### Eclipse Config
|
||||
After importing the project into Eclipse, you may see the following error:
|
||||
|
|
8
pom.xml
8
pom.xml
|
@ -49,8 +49,6 @@
|
|||
<module>core-java-8</module>
|
||||
<module>core-java-concurrency</module>
|
||||
<module>couchbase</module>
|
||||
<module>cas/cas-server</module>
|
||||
<module>cas/cas-secured-app</module>
|
||||
|
||||
<module>deltaspike</module>
|
||||
<module>dozer</module>
|
||||
|
@ -60,7 +58,6 @@
|
|||
<!--<module>ejb</module>-->
|
||||
|
||||
<module>feign</module>
|
||||
<module>flyway</module>
|
||||
|
||||
<!-- <module>testing-modules/gatling</module> --> <!-- not meant to run as part of the standard build -->
|
||||
|
||||
|
@ -141,8 +138,8 @@
|
|||
<module>persistence-modules/solr</module>
|
||||
<module>spark-java</module>
|
||||
<!-- <module>spring-5</module>-->
|
||||
<module>spring-5-reactive</module>
|
||||
<module>spring-5-mvc</module>
|
||||
<module>spring-acl</module>
|
||||
<module>spring-activiti</module>
|
||||
<module>spring-akka</module>
|
||||
<module>spring-amqp</module>
|
||||
|
@ -175,8 +172,9 @@
|
|||
<module>spring-hibernate4</module>
|
||||
<module>persistence-modules/spring-hibernate-5</module>
|
||||
<module>spring-integration</module>
|
||||
<module>spring-jenkins-pipeline</module>
|
||||
<module>spring-jersey</module>
|
||||
<module>spring-jmeter-jenkins</module>
|
||||
<module>jmeter</module>
|
||||
<module>spring-jms</module>
|
||||
<module>spring-jooq</module>
|
||||
<module>persistence-modules/spring-jpa</module>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#folders#
|
||||
.idea
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
|
@ -0,0 +1,15 @@
|
|||
## Spring REST Example Project
|
||||
|
||||
### The Course
|
||||
The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||
|
||||
### Relevant Articles
|
||||
|
||||
- [Concurrent Test Execution in Spring 5](http://www.baeldung.com/spring-5-concurrent-tests)
|
||||
- [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web)
|
||||
- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching)
|
||||
- [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient)
|
||||
- [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans)
|
||||
- [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](http://www.baeldung.com/spring-5-junit-config)
|
||||
- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive)
|
||||
- [Spring 5 Testing with @EnabledIf Annotation](https://github.com/eugenp/tutorials/tree/master/spring-5)
|
|
@ -0,0 +1,201 @@
|
|||
<?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-5-reactive-client</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-5</name>
|
||||
<description>spring 5 sample project about new features</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.0.M7</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</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-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectreactor</groupId>
|
||||
<artifactId>reactor-spring</artifactId>
|
||||
<version>${reactor-spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.json.bind</groupId>
|
||||
<artifactId>javax.json.bind-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Dependencies for Yasson -->
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>org.eclipse</groupId> -->
|
||||
<!-- <artifactId>yasson</artifactId> -->
|
||||
<!-- <version>1.0</version> -->
|
||||
<!-- </dependency> -->
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>org.glassfish</groupId> -->
|
||||
<!-- <artifactId>javax.json</artifactId> -->
|
||||
<!-- <version>1.1.2</version> -->
|
||||
<!-- </dependency> -->
|
||||
<!-- Dependencies for Johnzon -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-json_1.1_spec</artifactId>
|
||||
<version>${geronimo-json_1.1_spec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.johnzon</groupId>
|
||||
<artifactId>johnzon-jsonb</artifactId>
|
||||
</dependency>
|
||||
<!-- utils -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- runtime and test scoped -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>4.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-surefire-provider</artifactId>
|
||||
<version>${junit.platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-runner</artifactId>
|
||||
<version>${junit.platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.Spring5Application</mainClass>
|
||||
<layout>JAR</layout>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<forkCount>3</forkCount>
|
||||
<reuseForks>true</reuseForks>
|
||||
<parallel>methods</parallel>
|
||||
<useUnlimitedThreads>true</useUnlimitedThreads>
|
||||
<excludes>
|
||||
<exclude>**/*IntegrationTest.java</exclude>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<junit.platform.version>1.0.0</junit.platform.version>
|
||||
<junit.jupiter.version>5.0.0</junit.jupiter.version>
|
||||
<maven-surefire-plugin.version>2.20</maven-surefire-plugin.version>
|
||||
<spring.version>5.0.1.RELEASE</spring.version>
|
||||
<reactor-spring.version>1.0.1.RELEASE</reactor-spring.version>
|
||||
<johnzon.version>1.1.3</johnzon.version>
|
||||
<jsonb-api.version>1.0</jsonb-api.version>
|
||||
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.reactive.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class Foo {
|
||||
|
||||
private long id;
|
||||
private String name;
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
logging.level.root=INFO
|
||||
|
||||
server.port=8081
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
# Pattern of log message for console appender
|
||||
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="INFO" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="stdout" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
version="3.1">
|
||||
|
||||
<display-name>Spring Functional Application</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>functional</servlet-name>
|
||||
<servlet-class>com.baeldung.functional.RootServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
<async-supported>true</async-supported>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>functional</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
</web-app>
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.reactive;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import com.baeldung.reactive.model.Foo;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@SpringBootTest
|
||||
public class ReactiveIntegrationTest {
|
||||
|
||||
private WebClient client;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
client = WebClient.create("http://localhost:8080");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Test
|
||||
public void whenMonoReactiveEndpointIsConsumed_thenCorrectOutput() {
|
||||
final Mono<ClientResponse> fooMono = client.get().uri("/foos/123").exchange().log();
|
||||
|
||||
System.out.println(fooMono.subscribe());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenFluxReactiveEndpointIsConsumed_thenCorrectOutput() throws InterruptedException {
|
||||
client.get().uri("/foos")
|
||||
.retrieve()
|
||||
.bodyToFlux(Foo.class).log()
|
||||
.subscribe(System.out::println);
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.baeldung.reactive;
|
||||
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import com.baeldung.reactive.model.Foo;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Spring5ReactiveTestApplication {
|
||||
|
||||
@Bean
|
||||
public WebClient client() {
|
||||
return WebClient.create("http://localhost:8080");
|
||||
}
|
||||
|
||||
@Bean
|
||||
CommandLineRunner cmd(WebClient client) {
|
||||
return args -> {
|
||||
client.get().uri("/foos2")
|
||||
.retrieve()
|
||||
.bodyToFlux(Foo.class).log()
|
||||
.subscribe(System.out::println);
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Spring5ReactiveTestApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
# Pattern of log message for console appender
|
||||
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="INFO" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="stdout" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,12 @@
|
|||
#folders#
|
||||
.idea
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
|
@ -0,0 +1,15 @@
|
|||
## Spring REST Example Project
|
||||
|
||||
### The Course
|
||||
The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||
|
||||
### Relevant Articles
|
||||
|
||||
- [Concurrent Test Execution in Spring 5](http://www.baeldung.com/spring-5-concurrent-tests)
|
||||
- [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web)
|
||||
- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching)
|
||||
- [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient)
|
||||
- [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans)
|
||||
- [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](http://www.baeldung.com/spring-5-junit-config)
|
||||
- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive)
|
||||
- [Spring 5 Testing with @EnabledIf Annotation](https://github.com/eugenp/tutorials/tree/master/spring-5)
|
|
@ -0,0 +1,201 @@
|
|||
<?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-5-reactive</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-5</name>
|
||||
<description>spring 5 sample project about new features</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.0.M7</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</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-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectreactor</groupId>
|
||||
<artifactId>reactor-spring</artifactId>
|
||||
<version>${reactor-spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.json.bind</groupId>
|
||||
<artifactId>javax.json.bind-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Dependencies for Yasson -->
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>org.eclipse</groupId> -->
|
||||
<!-- <artifactId>yasson</artifactId> -->
|
||||
<!-- <version>1.0</version> -->
|
||||
<!-- </dependency> -->
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>org.glassfish</groupId> -->
|
||||
<!-- <artifactId>javax.json</artifactId> -->
|
||||
<!-- <version>1.1.2</version> -->
|
||||
<!-- </dependency> -->
|
||||
<!-- Dependencies for Johnzon -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-json_1.1_spec</artifactId>
|
||||
<version>${geronimo-json_1.1_spec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.johnzon</groupId>
|
||||
<artifactId>johnzon-jsonb</artifactId>
|
||||
</dependency>
|
||||
<!-- utils -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- runtime and test scoped -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>4.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-surefire-provider</artifactId>
|
||||
<version>${junit.platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-runner</artifactId>
|
||||
<version>${junit.platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.Spring5Application</mainClass>
|
||||
<layout>JAR</layout>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<forkCount>3</forkCount>
|
||||
<reuseForks>true</reuseForks>
|
||||
<parallel>methods</parallel>
|
||||
<useUnlimitedThreads>true</useUnlimitedThreads>
|
||||
<excludes>
|
||||
<exclude>**/*IntegrationTest.java</exclude>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<junit.platform.version>1.0.0</junit.platform.version>
|
||||
<junit.jupiter.version>5.0.0</junit.jupiter.version>
|
||||
<maven-surefire-plugin.version>2.20</maven-surefire-plugin.version>
|
||||
<spring.version>5.0.1.RELEASE</spring.version>
|
||||
<reactor-spring.version>1.0.1.RELEASE</reactor-spring.version>
|
||||
<johnzon.version>1.1.3</johnzon.version>
|
||||
<jsonb-api.version>1.0</jsonb-api.version>
|
||||
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.reactive;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Spring5ReactiveApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Spring5ReactiveApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.baeldung.reactive.controller;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.reactive.model.Foo;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
@RestController
|
||||
public class FooReactiveController {
|
||||
|
||||
@GetMapping("/foos/{id}")
|
||||
public Mono<Foo> getFoo(@PathVariable("id") long id) {
|
||||
return Mono.just(new Foo(id, randomAlphabetic(6)));
|
||||
}
|
||||
|
||||
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/foos")
|
||||
public Flux<Foo> getAllFoos2() {
|
||||
final Flux<Foo> foosFlux = Flux.fromStream(Stream.generate(() -> new Foo(new Random().nextLong(), randomAlphabetic(6))));
|
||||
final Flux<Long> emmitFlux = Flux.interval(Duration.ofSeconds(1));
|
||||
return Flux.zip(foosFlux, emmitFlux).map(Tuple2::getT1);
|
||||
}
|
||||
|
||||
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/foos2")
|
||||
public Flux<Foo> getAllFoos() {
|
||||
final Flux<Foo> flux = Flux.<Foo> create(fluxSink -> {
|
||||
while (true) {
|
||||
fluxSink.next(new Foo(new Random().nextLong(), randomAlphabetic(6)));
|
||||
}
|
||||
}).sample(Duration.ofSeconds(1)).log();
|
||||
|
||||
return flux;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.reactive.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class Foo {
|
||||
|
||||
private long id;
|
||||
private String name;
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
logging.level.root=INFO
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
version="3.1">
|
||||
|
||||
<display-name>Spring Functional Application</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>functional</servlet-name>
|
||||
<servlet-class>com.baeldung.functional.RootServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
<async-supported>true</async-supported>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>functional</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
</web-app>
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.reactive;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.reactive.model.Foo;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
public class FluxUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenFluxIsConstructed_thenCorrect() {
|
||||
final Flux<Foo> flux = Flux.<Foo> create(fluxSink -> {
|
||||
while (true) {
|
||||
fluxSink.next(new Foo(new Random().nextLong(), randomAlphabetic(6)));
|
||||
}
|
||||
}).sample(Duration.ofSeconds(1)).log();
|
||||
|
||||
flux.subscribe();
|
||||
|
||||
assertNotNull(flux);
|
||||
}
|
||||
|
||||
}
|
|
@ -11,3 +11,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient)
|
||||
- [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans)
|
||||
- [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](http://www.baeldung.com/spring-5-junit-config)
|
||||
- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive)
|
||||
- [Spring 5 Testing with @EnabledIf Annotation](https://github.com/eugenp/tutorials/tree/master/spring-5)
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.baeldung.web;
|
|||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
|
|
|
@ -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-acl</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>spring-acl</name>
|
||||
<description>Spring ACL</description>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-boot-5</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-5</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<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</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache-core</artifactId>
|
||||
<version>2.6.11</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -1,80 +0,0 @@
|
|||
package org.baeldung.acl.config;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.cache.ehcache.EhCacheFactoryBean;
|
||||
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.acls.AclPermissionCacheOptimizer;
|
||||
import org.springframework.security.acls.AclPermissionEvaluator;
|
||||
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
||||
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.domain.EhCacheBasedAclCache;
|
||||
import org.springframework.security.acls.jdbc.BasicLookupStrategy;
|
||||
import org.springframework.security.acls.jdbc.JdbcMutableAclService;
|
||||
import org.springframework.security.acls.jdbc.LookupStrategy;
|
||||
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
public class ACLContext {
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Bean
|
||||
public EhCacheBasedAclCache aclCache() {
|
||||
return new EhCacheBasedAclCache(aclEhCacheFactoryBean().getObject(), permissionGrantingStrategy(), aclAuthorizationStrategy());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EhCacheFactoryBean aclEhCacheFactoryBean() {
|
||||
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
|
||||
ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
|
||||
ehCacheFactoryBean.setCacheName("aclCache");
|
||||
return ehCacheFactoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EhCacheManagerFactoryBean aclCacheManager() {
|
||||
return new EhCacheManagerFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PermissionGrantingStrategy permissionGrantingStrategy() {
|
||||
return new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AclAuthorizationStrategy aclAuthorizationStrategy() {
|
||||
return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMIN"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
|
||||
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
AclPermissionEvaluator permissionEvaluator = new AclPermissionEvaluator(aclService());
|
||||
expressionHandler.setPermissionEvaluator(permissionEvaluator);
|
||||
expressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService()));
|
||||
return expressionHandler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LookupStrategy lookupStrategy() {
|
||||
return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), new ConsoleAuditLogger());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JdbcMutableAclService aclService() {
|
||||
return new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package org.baeldung.acl.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
public class AclMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Autowired
|
||||
MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler;
|
||||
|
||||
@Override
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
return defaultMethodSecurityExpressionHandler;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package org.baeldung.acl.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@EnableJpaRepositories(basePackages = "org.baeldung.acl.persistence.dao")
|
||||
@PropertySource("classpath:org.baeldung.acl.datasource.properties")
|
||||
@EntityScan(basePackages={ "org.baeldung.acl.persistence.entity" })
|
||||
public class JPAPersistenceConfig {
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package org.baeldung.acl.persistence.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.baeldung.acl.persistence.entity.NoticeMessage;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
public interface NoticeMessageRepository extends JpaRepository<NoticeMessage, Long>{
|
||||
|
||||
@PostFilter("hasPermission(filterObject, 'READ')")
|
||||
List<NoticeMessage> findAll();
|
||||
|
||||
@PostAuthorize("hasPermission(returnObject, 'READ')")
|
||||
NoticeMessage findById(Integer id);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@PreAuthorize("hasPermission(#noticeMessage, 'WRITE')")
|
||||
NoticeMessage save(@Param("noticeMessage")NoticeMessage noticeMessage);
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package org.baeldung.acl.persistence.entity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name="system_message")
|
||||
public class NoticeMessage {
|
||||
|
||||
@Id
|
||||
@Column
|
||||
private Integer id;
|
||||
@Column
|
||||
private String content;
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
INSERT INTO system_message(id,content) VALUES (1,'First Level Message');
|
||||
INSERT INTO system_message(id,content) VALUES (2,'Second Level Message');
|
||||
INSERT INTO system_message(id,content) VALUES (3,'Third Level Message');
|
||||
|
||||
INSERT INTO acl_class (id, class) VALUES
|
||||
(1, 'org.baeldung.acl.persistence.entity.NoticeMessage');
|
||||
|
||||
INSERT INTO acl_sid (id, principal, sid) VALUES
|
||||
(1, 1, 'manager'),
|
||||
(2, 1, 'hr'),
|
||||
(3, 1, 'admin'),
|
||||
(4, 0, 'ROLE_EDITOR');
|
||||
|
||||
INSERT INTO acl_object_identity (id, object_id_class, object_id_identity, parent_object, owner_sid, entries_inheriting) VALUES
|
||||
(1, 1, 1, NULL, 3, 0),
|
||||
(2, 1, 2, NULL, 3, 0),
|
||||
(3, 1, 3, NULL, 3, 0)
|
||||
;
|
||||
|
||||
INSERT INTO acl_entry (id, acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure) VALUES
|
||||
(1, 1, 1, 1, 1, 1, 1, 1),
|
||||
(2, 1, 2, 1, 2, 1, 1, 1),
|
||||
(3, 1, 3, 4, 1, 1, 1, 1),
|
||||
(4, 2, 1, 2, 1, 1, 1, 1),
|
||||
(5, 2, 2, 4, 1, 1, 1, 1),
|
||||
(6, 3, 1, 4, 1, 1, 1, 1),
|
||||
(7, 3, 2, 4, 2, 1, 1, 1)
|
||||
;
|
|
@ -1,58 +0,0 @@
|
|||
create table system_message (id integer not null, content varchar(255), primary key (id));
|
||||
|
||||
CREATE TABLE IF NOT EXISTS acl_sid (
|
||||
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
principal tinyint(1) NOT NULL,
|
||||
sid varchar(100) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY unique_uk_1 (sid,principal)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS acl_class (
|
||||
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
class varchar(255) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY unique_uk_2 (class)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS acl_entry (
|
||||
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
acl_object_identity bigint(20) NOT NULL,
|
||||
ace_order int(11) NOT NULL,
|
||||
sid bigint(20) NOT NULL,
|
||||
mask int(11) NOT NULL,
|
||||
granting tinyint(1) NOT NULL,
|
||||
audit_success tinyint(1) NOT NULL,
|
||||
audit_failure tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY unique_uk_4 (acl_object_identity,ace_order)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS acl_object_identity (
|
||||
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
object_id_class bigint(20) NOT NULL,
|
||||
object_id_identity bigint(20) NOT NULL,
|
||||
parent_object bigint(20) DEFAULT NULL,
|
||||
owner_sid bigint(20) DEFAULT NULL,
|
||||
entries_inheriting tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY unique_uk_3 (object_id_class,object_id_identity)
|
||||
);
|
||||
|
||||
ALTER TABLE acl_entry
|
||||
ADD FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id);
|
||||
|
||||
ALTER TABLE acl_entry
|
||||
ADD FOREIGN KEY (sid) REFERENCES acl_sid(id);
|
||||
|
||||
--
|
||||
-- Constraints for table acl_object_identity
|
||||
--
|
||||
ALTER TABLE acl_object_identity
|
||||
ADD FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id);
|
||||
|
||||
ALTER TABLE acl_object_identity
|
||||
ADD FOREIGN KEY (object_id_class) REFERENCES acl_class (id);
|
||||
|
||||
ALTER TABLE acl_object_identity
|
||||
ADD FOREIGN KEY (owner_sid) REFERENCES acl_sid (id);
|
|
@ -1,12 +0,0 @@
|
|||
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
|
||||
spring.h2.console.path=/myconsole
|
||||
spring.h2.console.enabled=true
|
||||
spring.datasource.initialize=true
|
||||
spring.datasource.schema=classpath:acl-schema.sql
|
||||
spring.datasource.data=classpath:acl-data.sql
|
|
@ -1,119 +0,0 @@
|
|||
package org.baeldung.acl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.baeldung.acl.persistence.dao.NoticeMessageRepository;
|
||||
import org.baeldung.acl.persistence.entity.NoticeMessage;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
import org.springframework.test.context.web.ServletTestExecutionListener;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TestExecutionListeners(listeners={ServletTestExecutionListener.class,
|
||||
DependencyInjectionTestExecutionListener.class,
|
||||
DirtiesContextTestExecutionListener.class,
|
||||
TransactionalTestExecutionListener.class,
|
||||
WithSecurityContextTestExecutionListener.class})
|
||||
public class SpringAclTest extends AbstractJUnit4SpringContextTests{
|
||||
|
||||
private static Integer FIRST_MESSAGE_ID = 1;
|
||||
private static Integer SECOND_MESSAGE_ID = 2;
|
||||
private static Integer THIRD_MESSAGE_ID = 3;
|
||||
private static String EDITTED_CONTENT = "EDITED";
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("org.baeldung.acl.*")
|
||||
public static class SpringConfig {
|
||||
|
||||
}
|
||||
|
||||
@Autowired
|
||||
NoticeMessageRepository repo;
|
||||
|
||||
@Test
|
||||
@WithMockUser(username="manager")
|
||||
public void givenUsernameManager_whenFindAllMessage_thenReturnFirstMessage(){
|
||||
List<NoticeMessage> details = repo.findAll();
|
||||
assertNotNull(details);
|
||||
assertEquals(1,details.size());
|
||||
assertEquals(FIRST_MESSAGE_ID,details.get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username="manager")
|
||||
public void givenUsernameManager_whenFindFirstMessageByIdAndUpdateFirstMessageContent_thenOK(){
|
||||
NoticeMessage firstMessage = repo.findById(FIRST_MESSAGE_ID);
|
||||
assertNotNull(firstMessage);
|
||||
assertEquals(FIRST_MESSAGE_ID,firstMessage.getId());
|
||||
|
||||
firstMessage.setContent(EDITTED_CONTENT);
|
||||
repo.save(firstMessage);
|
||||
|
||||
NoticeMessage editedFirstMessage = repo.findById(FIRST_MESSAGE_ID);
|
||||
assertNotNull(editedFirstMessage);
|
||||
assertEquals(FIRST_MESSAGE_ID,editedFirstMessage.getId());
|
||||
assertEquals(EDITTED_CONTENT,editedFirstMessage.getContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username="hr")
|
||||
public void givenUsernameHr_whenFindMessageById2_thenOK(){
|
||||
NoticeMessage secondMessage = repo.findById(SECOND_MESSAGE_ID);
|
||||
assertNotNull(secondMessage);
|
||||
assertEquals(SECOND_MESSAGE_ID,secondMessage.getId());
|
||||
}
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
@WithMockUser(username="hr")
|
||||
public void givenUsernameHr_whenUpdateMessageWithId2_thenFail(){
|
||||
NoticeMessage secondMessage = new NoticeMessage();
|
||||
secondMessage.setId(SECOND_MESSAGE_ID);
|
||||
secondMessage.setContent(EDITTED_CONTENT);
|
||||
repo.save(secondMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(roles={"EDITOR"})
|
||||
public void givenRoleEditor_whenFindAllMessage_thenReturnThreeMessage(){
|
||||
List<NoticeMessage> details = repo.findAll();
|
||||
assertNotNull(details);
|
||||
assertEquals(3,details.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(roles={"EDITOR"})
|
||||
public void givenRoleEditor_whenUpdateThirdMessage_thenOK(){
|
||||
NoticeMessage thirdMessage = new NoticeMessage();
|
||||
thirdMessage.setId(THIRD_MESSAGE_ID);
|
||||
thirdMessage.setContent(EDITTED_CONTENT);
|
||||
repo.save(thirdMessage);
|
||||
}
|
||||
|
||||
@Test(expected=AccessDeniedException.class)
|
||||
@WithMockUser(roles={"EDITOR"})
|
||||
public void givenRoleEditor_whenFindFirstMessageByIdAndUpdateFirstMessageContent_thenFail(){
|
||||
NoticeMessage firstMessage = repo.findById(FIRST_MESSAGE_ID);
|
||||
assertNotNull(firstMessage);
|
||||
assertEquals(FIRST_MESSAGE_ID,firstMessage.getId());
|
||||
firstMessage.setContent(EDITTED_CONTENT);
|
||||
repo.save(firstMessage);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,3 +3,4 @@
|
|||
- [Implementing a Custom Spring AOP Annotation](http://www.baeldung.com/spring-aop-annotation)
|
||||
- [Intro to AspectJ](http://www.baeldung.com/aspectj)
|
||||
- [Spring Performance Logging](http://www.baeldung.com/spring-performance-logging)
|
||||
- [Introduction to Spring AOP](http://www.baeldung.com/spring-aop)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [A Quick Guide to Using Keycloak with Spring Boot](http://www.baeldung.com/spring-boot-keycloak)
|
|
@ -28,4 +28,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [Spring Boot and Togglz Aspect](http://www.baeldung.com/spring-togglz)
|
||||
- [Getting Started with GraphQL and Spring Boot](http://www.baeldung.com/spring-graphql)
|
||||
- [Guide to Spring Type Conversions](http://www.baeldung.com/spring-type-conversions)
|
||||
|
||||
- [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql)
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
## Spring Cloud CLI
|
||||
|
||||
### Relevant Articles:
|
||||
- [Introduction to Spring Cloud CLI](http://www.baeldung.com/introduction-to-spring-cloud-cli/)
|
||||
- [Introduction to Spring Cloud CLI](http://www.baeldung.com/spring-cloud-cli)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue