Merge remote-tracking branch 'eugenp/master'
This commit is contained in:
commit
5e3ab6f573
|
@ -15,3 +15,4 @@
|
||||||
- [Introduction to JGraphT](http://www.baeldung.com/jgrapht)
|
- [Introduction to JGraphT](http://www.baeldung.com/jgrapht)
|
||||||
- [Introduction to Minimax Algorithm](http://www.baeldung.com/java-minimax-algorithm)
|
- [Introduction to Minimax Algorithm](http://www.baeldung.com/java-minimax-algorithm)
|
||||||
- [How to Calculate Levenshtein Distance in Java?](http://www.baeldung.com/java-levenshtein-distance)
|
- [How to Calculate Levenshtein Distance in Java?](http://www.baeldung.com/java-levenshtein-distance)
|
||||||
|
- [How to Find the Kth Largest Element in Java](http://www.baeldung.com/java-kth-largest-element)
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.staticclass;
|
||||||
|
|
||||||
|
public class Pizza {
|
||||||
|
|
||||||
|
private static String cookedCount;
|
||||||
|
private boolean isThinCrust;
|
||||||
|
|
||||||
|
// Accessible globally
|
||||||
|
public static class PizzaSalesCounter {
|
||||||
|
|
||||||
|
private static String orderedCount;
|
||||||
|
public static String deliveredCount;
|
||||||
|
|
||||||
|
PizzaSalesCounter() {
|
||||||
|
System.out.println("Static field of enclosing class is "
|
||||||
|
+ Pizza.cookedCount);
|
||||||
|
System.out.println("Non-static field of enclosing class is "
|
||||||
|
+ new Pizza().isThinCrust);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pizza() {
|
||||||
|
System.out.println("Non private static field of static class is "
|
||||||
|
+ PizzaSalesCounter.deliveredCount);
|
||||||
|
System.out.println("Private static field of static class is "
|
||||||
|
+ PizzaSalesCounter.orderedCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] a) {
|
||||||
|
// Create instance of the static class without an instance of enclosing class
|
||||||
|
new Pizza.PizzaSalesCounter();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?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.samples</groupId>
|
||||||
|
<artifactId>java-vavr-stream</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.vavr</groupId>
|
||||||
|
<artifactId>vavr</artifactId>
|
||||||
|
<version>0.9.2</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,98 @@
|
||||||
|
package com.baeldung.samples.java.vavr;
|
||||||
|
|
||||||
|
import io.vavr.collection.Stream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author baeldung
|
||||||
|
*/
|
||||||
|
public class VavrSampler {
|
||||||
|
|
||||||
|
static int[] intArray = new int[]{1, 2, 4};
|
||||||
|
static List<Integer> intList = new ArrayList<Integer>();
|
||||||
|
static int[][] intOfInts = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
vavrStreamElementAccess();
|
||||||
|
System.out.println("====================================");
|
||||||
|
vavrParallelStreamAccess();
|
||||||
|
System.out.println("====================================");
|
||||||
|
jdkFlatMapping();
|
||||||
|
System.out.println("====================================");
|
||||||
|
vavrStreamManipulation();
|
||||||
|
System.out.println("====================================");
|
||||||
|
vavrStreamDistinct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void vavrStreamElementAccess() {
|
||||||
|
System.out.println("Vavr Element Access");
|
||||||
|
System.out.println("====================================");
|
||||||
|
Stream<Integer> vavredStream = Stream.ofAll(intArray);
|
||||||
|
System.out.println("Vavr index access: " + vavredStream.get(2));
|
||||||
|
System.out.println("Vavr head element access: " + vavredStream.get());
|
||||||
|
|
||||||
|
Stream<String> vavredStringStream = Stream.of("foo", "bar", "baz");
|
||||||
|
System.out.println("Find foo " + vavredStringStream.indexOf("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void vavrParallelStreamAccess() {
|
||||||
|
try {
|
||||||
|
System.out.println("Vavr Stream Concurrent Modification");
|
||||||
|
System.out.println("====================================");
|
||||||
|
Stream<Integer> vavrStream = Stream.ofAll(intList);
|
||||||
|
intList.add(5);
|
||||||
|
vavrStream.forEach(i -> System.out.println("in a Vavr Stream: " + i));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<Integer> wrapped = Stream.ofAll(intArray);
|
||||||
|
intArray[2] = 5;
|
||||||
|
wrapped.forEach(i -> System.out.println("Vavr looped " + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void jdkFlatMapping() {
|
||||||
|
System.out.println("JDK FlatMap -> Uncomment line 68 to test");
|
||||||
|
System.out.println("====================================");
|
||||||
|
int[][] intOfInts = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
|
||||||
|
|
||||||
|
IntStream mapToInt = Arrays.stream(intOfInts)
|
||||||
|
.map(intArr -> Arrays.stream(intArr))
|
||||||
|
.flatMapToInt(val -> val.map(n -> {
|
||||||
|
return n * n;
|
||||||
|
}))
|
||||||
|
.peek(n -> System.out.println("Peeking at " + n));
|
||||||
|
//Uncomment to execute pipeline
|
||||||
|
//mapToInt.forEach(n -> System.out.println("FlatMapped Result "+n));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void vavrStreamManipulation() {
|
||||||
|
System.out.println("Vavr Stream Manipulation");
|
||||||
|
System.out.println("====================================");
|
||||||
|
List<String> stringList = new ArrayList<>();
|
||||||
|
stringList.add("foo");
|
||||||
|
stringList.add("bar");
|
||||||
|
stringList.add("baz");
|
||||||
|
Stream<String> vavredStream = Stream.ofAll(stringList);
|
||||||
|
vavredStream.forEach(item -> System.out.println("Vavr Stream item: " + item));
|
||||||
|
Stream<String> vavredStream2 = vavredStream.insert(2, "buzz");
|
||||||
|
vavredStream2.forEach(item -> System.out.println("Vavr Stream item after stream addition: " + item));
|
||||||
|
stringList.forEach(item -> System.out.println("List item after stream addition: " + item));
|
||||||
|
Stream<String> deletionStream = vavredStream.remove("bar");
|
||||||
|
deletionStream.forEach(item -> System.out.println("Vavr Stream item after stream item deletion: " + item));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void vavrStreamDistinct() {
|
||||||
|
Stream<String> vavredStream = Stream.of("foo", "bar", "baz", "buxx", "bar", "bar", "foo");
|
||||||
|
Stream<String> distinctVavrStream = vavredStream.distinctBy((y, z) -> {
|
||||||
|
return y.compareTo(z);
|
||||||
|
});
|
||||||
|
distinctVavrStream.forEach(item -> System.out.println("Vavr Stream item after distinct query " + item));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
2
pom.xml
2
pom.xml
|
@ -87,6 +87,7 @@
|
||||||
<!-- <module>persistence-modules/java-cassandra</module> -->
|
<!-- <module>persistence-modules/java-cassandra</module> -->
|
||||||
<module>vavr</module>
|
<module>vavr</module>
|
||||||
<module>java-lite</module>
|
<module>java-lite</module>
|
||||||
|
<module>java-vavr-stream</module>
|
||||||
<module>javax-servlets</module>
|
<module>javax-servlets</module>
|
||||||
<module>javaxval</module>
|
<module>javaxval</module>
|
||||||
<module>jaxb</module>
|
<module>jaxb</module>
|
||||||
|
@ -203,7 +204,6 @@
|
||||||
<module>spring-protobuf</module>
|
<module>spring-protobuf</module>
|
||||||
<module>spring-quartz</module>
|
<module>spring-quartz</module>
|
||||||
<module>spring-rest-angular</module>
|
<module>spring-rest-angular</module>
|
||||||
<module>spring-rest-docs</module>
|
|
||||||
<module>spring-rest-full</module>
|
<module>spring-rest-full</module>
|
||||||
<module>spring-rest-query-language</module>
|
<module>spring-rest-query-language</module>
|
||||||
<module>spring-rest</module>
|
<module>spring-rest</module>
|
||||||
|
|
|
@ -12,4 +12,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||||
- [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans)
|
- [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)
|
- [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 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)
|
- [Spring 5 Testing with @EnabledIf Annotation](http://www.baeldung.com/sring-5-enabledif)
|
||||||
|
- [Introduction to Spring REST Docs](http://www.baeldung.com/spring-rest-docs)
|
||||||
|
|
|
@ -39,6 +39,14 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectreactor</groupId>
|
<groupId>org.projectreactor</groupId>
|
||||||
<artifactId>reactor-spring</artifactId>
|
<artifactId>reactor-spring</artifactId>
|
||||||
|
@ -135,6 +143,23 @@
|
||||||
<version>${junit.platform.version}</version>
|
<version>${junit.platform.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- restdocs -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.restdocs</groupId>
|
||||||
|
<artifactId>spring-restdocs-mockmvc</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.restdocs</groupId>
|
||||||
|
<artifactId>spring-restdocs-webtestclient</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.restdocs</groupId>
|
||||||
|
<artifactId>spring-restdocs-restassured</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -163,6 +188,29 @@
|
||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.asciidoctor</groupId>
|
||||||
|
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||||
|
<version>${asciidoctor-plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>generate-docs</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>process-asciidoc</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<backend>html</backend>
|
||||||
|
<doctype>book</doctype>
|
||||||
|
<attributes>
|
||||||
|
<snippets>${snippetsDirectory}</snippets>
|
||||||
|
</attributes>
|
||||||
|
<sourceDirectory>src/docs/asciidocs</sourceDirectory>
|
||||||
|
<outputDirectory>target/generated-docs</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -199,6 +247,8 @@
|
||||||
<johnzon.version>1.1.3</johnzon.version>
|
<johnzon.version>1.1.3</johnzon.version>
|
||||||
<jsonb-api.version>1.0</jsonb-api.version>
|
<jsonb-api.version>1.0</jsonb-api.version>
|
||||||
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
||||||
|
<asciidoctor-plugin.version>1.5.6</asciidoctor-plugin.version>
|
||||||
|
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -55,13 +55,6 @@ use of HTTP status codes.
|
||||||
| The requested resource did not exist
|
| The requested resource did not exist
|
||||||
|===
|
|===
|
||||||
|
|
||||||
[[overview-headers]]
|
|
||||||
== Headers
|
|
||||||
|
|
||||||
Every response has the following header(s):
|
|
||||||
|
|
||||||
include::{snippets}/headers-example/response-headers.adoc[]
|
|
||||||
|
|
||||||
[[overview-hypermedia]]
|
[[overview-hypermedia]]
|
||||||
== Hypermedia
|
== Hypermedia
|
||||||
|
|
||||||
|
@ -86,18 +79,14 @@ The index provides the entry point into the service.
|
||||||
|
|
||||||
A `GET` request is used to access the index
|
A `GET` request is used to access the index
|
||||||
|
|
||||||
==== Response structure
|
==== Request structure
|
||||||
|
|
||||||
include::{snippets}/index-example/http-response.adoc[]
|
include::{snippets}/index-example/http-request.adoc[]
|
||||||
|
|
||||||
==== Example response
|
==== Example response
|
||||||
|
|
||||||
include::{snippets}/index-example/http-response.adoc[]
|
include::{snippets}/index-example/http-response.adoc[]
|
||||||
|
|
||||||
==== Example request
|
|
||||||
|
|
||||||
include::{snippets}/index-example/http-request.adoc[]
|
|
||||||
|
|
||||||
==== CURL request
|
==== CURL request
|
||||||
|
|
||||||
include::{snippets}/index-example/curl-request.adoc[]
|
include::{snippets}/index-example/curl-request.adoc[]
|
||||||
|
@ -113,12 +102,12 @@ include::{snippets}/index-example/links.adoc[]
|
||||||
|
|
||||||
The CRUD provides the entry point into the service.
|
The CRUD provides the entry point into the service.
|
||||||
|
|
||||||
[[resources-crud-access]]
|
[[resources-crud-get]]
|
||||||
=== Accessing the crud GET
|
=== Accessing the crud GET
|
||||||
|
|
||||||
A `GET` request is used to access the CRUD read
|
A `GET` request is used to access the CRUD read.
|
||||||
|
|
||||||
==== Response structure
|
==== Request structure
|
||||||
|
|
||||||
include::{snippets}/crud-get-example/http-request.adoc[]
|
include::{snippets}/crud-get-example/http-request.adoc[]
|
||||||
|
|
||||||
|
@ -130,12 +119,12 @@ include::{snippets}/crud-get-example/http-response.adoc[]
|
||||||
|
|
||||||
include::{snippets}/crud-get-example/curl-request.adoc[]
|
include::{snippets}/crud-get-example/curl-request.adoc[]
|
||||||
|
|
||||||
[[resources-crud-access]]
|
[[resources-crud-post]]
|
||||||
=== Accessing the crud POST
|
=== Accessing the crud POST
|
||||||
|
|
||||||
A `POST` request is used to access the CRUD create
|
A `POST` request is used to access the CRUD create.
|
||||||
|
|
||||||
==== Response structure
|
==== Request structure
|
||||||
|
|
||||||
include::{snippets}/crud-create-example/http-request.adoc[]
|
include::{snippets}/crud-create-example/http-request.adoc[]
|
||||||
|
|
||||||
|
@ -147,15 +136,18 @@ include::{snippets}/crud-create-example/http-response.adoc[]
|
||||||
|
|
||||||
include::{snippets}/crud-create-example/curl-request.adoc[]
|
include::{snippets}/crud-create-example/curl-request.adoc[]
|
||||||
|
|
||||||
[[resources-crud-access]]
|
[[resources-crud-delete]]
|
||||||
=== Accessing the crud DELETE
|
=== Accessing the crud DELETE
|
||||||
|
|
||||||
A `DELETE` request is used to access the CRUD create
|
A `DELETE` request is used to access the CRUD delete.
|
||||||
|
|
||||||
==== Response structure
|
==== Request structure
|
||||||
|
|
||||||
include::{snippets}/crud-delete-example/http-request.adoc[]
|
include::{snippets}/crud-delete-example/http-request.adoc[]
|
||||||
|
|
||||||
|
==== Path Parameters
|
||||||
|
include::{snippets}/crud-delete-example/path-parameters.adoc[]
|
||||||
|
|
||||||
==== Example response
|
==== Example response
|
||||||
|
|
||||||
include::{snippets}/crud-delete-example/http-response.adoc[]
|
include::{snippets}/crud-delete-example/http-response.adoc[]
|
||||||
|
@ -164,12 +156,12 @@ include::{snippets}/crud-delete-example/http-response.adoc[]
|
||||||
|
|
||||||
include::{snippets}/crud-delete-example/curl-request.adoc[]
|
include::{snippets}/crud-delete-example/curl-request.adoc[]
|
||||||
|
|
||||||
[[resources-crud-access]]
|
[[resources-crud-patch]]
|
||||||
=== Accessing the crud PATCH
|
=== Accessing the crud PATCH
|
||||||
|
|
||||||
A `PATCH` request is used to access the CRUD create
|
A `PATCH` request is used to access the CRUD update.
|
||||||
|
|
||||||
==== Response structure
|
==== Request structure
|
||||||
|
|
||||||
include::{snippets}/crud-patch-example/http-request.adoc[]
|
include::{snippets}/crud-patch-example/http-request.adoc[]
|
||||||
|
|
||||||
|
@ -181,12 +173,12 @@ include::{snippets}/crud-patch-example/http-response.adoc[]
|
||||||
|
|
||||||
include::{snippets}/crud-patch-example/curl-request.adoc[]
|
include::{snippets}/crud-patch-example/curl-request.adoc[]
|
||||||
|
|
||||||
[[resources-crud-access]]
|
[[resources-crud-put]]
|
||||||
=== Accessing the crud PUT
|
=== Accessing the crud PUT
|
||||||
|
|
||||||
A `PUT` request is used to access the CRUD create
|
A `PUT` request is used to access the CRUD update.
|
||||||
|
|
||||||
==== Response structure
|
==== Request structure
|
||||||
|
|
||||||
include::{snippets}/crud-put-example/http-request.adoc[]
|
include::{snippets}/crud-put-example/http-request.adoc[]
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.actuator;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.health.Health;
|
||||||
|
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DownstreamServiceReactiveHealthIndicator implements ReactiveHealthIndicator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Health> health() {
|
||||||
|
return checkDownstreamServiceHealth().onErrorResume(
|
||||||
|
ex -> Mono.just(new Health.Builder().down(ex).build())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<Health> checkDownstreamServiceHealth() {
|
||||||
|
// we could use WebClient to check health reactively
|
||||||
|
return Mono.just(new Health.Builder().up().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.baeldung.actuator;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.endpoint.annotation.*;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Endpoint(id = "features", enableByDefault = true)
|
||||||
|
public class FeaturesEndpoint {
|
||||||
|
|
||||||
|
private Map<String, Feature> features = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@ReadOperation
|
||||||
|
public Map<String, Feature> features() {
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadOperation
|
||||||
|
public Feature feature(@Selector String name) {
|
||||||
|
return features.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WriteOperation
|
||||||
|
public void configureFeature(@Selector String name, Feature feature) {
|
||||||
|
features.put(name, feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteOperation
|
||||||
|
public void deleteFeature(@Selector String name) {
|
||||||
|
features.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Feature {
|
||||||
|
private Boolean enabled;
|
||||||
|
|
||||||
|
public Boolean getEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(Boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.actuator;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||||
|
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
|
||||||
|
import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension;
|
||||||
|
import org.springframework.boot.actuate.info.InfoEndpoint;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@EndpointWebExtension(endpoint = InfoEndpoint.class)
|
||||||
|
public class InfoWebEndpointExtension {
|
||||||
|
|
||||||
|
private final InfoEndpoint delegate;
|
||||||
|
|
||||||
|
public InfoWebEndpointExtension(InfoEndpoint infoEndpoint) {
|
||||||
|
this.delegate = infoEndpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadOperation
|
||||||
|
public WebEndpointResponse<Map> info() {
|
||||||
|
Map<String, Object> info = this.delegate.info();
|
||||||
|
Integer status = getStatus(info);
|
||||||
|
return new WebEndpointResponse<>(info, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getStatus(Map<String, Object> info) {
|
||||||
|
// return 5xx if this is a snapshot
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,23 @@
|
||||||
package com.example;
|
package com.baeldung.restdocs;
|
||||||
|
|
||||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PatchMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@ -18,38 +25,38 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
@RequestMapping("/crud")
|
@RequestMapping("/crud")
|
||||||
public class CRUDController {
|
public class CRUDController {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET)
|
@GetMapping
|
||||||
@ResponseStatus(HttpStatus.OK)
|
public List<CrudInput> read(@RequestBody @Valid CrudInput crudInput) {
|
||||||
public List<CrudInput> read(@RequestBody CrudInput crudInput) {
|
List<CrudInput> returnList = new ArrayList<>();
|
||||||
List<CrudInput> returnList = new ArrayList<CrudInput>();
|
|
||||||
returnList.add(crudInput);
|
returnList.add(crudInput);
|
||||||
return returnList;
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResponseStatus(HttpStatus.CREATED)
|
@ResponseStatus(HttpStatus.CREATED)
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
@PostMapping
|
||||||
public HttpHeaders save(@RequestBody CrudInput crudInput) {
|
public HttpHeaders save(@RequestBody @Valid CrudInput crudInput) {
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.setLocation(linkTo(CRUDController.class).slash(crudInput.getTitle()).toUri());
|
httpHeaders.setLocation(linkTo(CRUDController.class).slash(crudInput.getId()).toUri());
|
||||||
return httpHeaders;
|
return httpHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
|
@DeleteMapping("/{id}")
|
||||||
@ResponseStatus(HttpStatus.OK)
|
@ResponseStatus(HttpStatus.OK)
|
||||||
HttpHeaders delete(@RequestBody CrudInput crudInput) {
|
HttpHeaders delete(@PathVariable("id") long id) {
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
return new HttpHeaders();
|
||||||
return httpHeaders;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
|
@PutMapping("/{id}")
|
||||||
@ResponseStatus(HttpStatus.ACCEPTED)
|
@ResponseStatus(HttpStatus.ACCEPTED)
|
||||||
void put(@PathVariable("id") long id, @RequestBody CrudInput crudInput) {
|
void put(@PathVariable("id") long id, @RequestBody CrudInput crudInput) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/{id}", method = RequestMethod.PATCH)
|
@PatchMapping("/{id}")
|
||||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
public List<CrudInput> patch(@PathVariable("id") long id, @RequestBody CrudInput crudInput) {
|
||||||
void patch(@PathVariable("id") long id, @RequestBody CrudInput crudInput) {
|
List<CrudInput> returnList = new ArrayList<CrudInput>();
|
||||||
|
crudInput.setId(id);
|
||||||
|
returnList.add(crudInput);
|
||||||
|
return returnList;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.baeldung.restdocs;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
public class CrudInput {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
private List<URI> tagUris;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public CrudInput(@JsonProperty("id") long id, @JsonProperty("title") String title, @JsonProperty("body") String body, @JsonProperty("tags") List<URI> tagUris) {
|
||||||
|
this.id=id;
|
||||||
|
this.title = title;
|
||||||
|
this.body = body;
|
||||||
|
this.tagUris = tagUris == null ? Collections.<URI> emptyList() : tagUris;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(String body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTagUris(List<URI> tagUris) {
|
||||||
|
this.tagUris = tagUris;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty("tags")
|
||||||
|
public List<URI> getTagUris() {
|
||||||
|
return this.tagUris;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
package com.example;
|
package com.baeldung.restdocs;
|
||||||
|
|
||||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||||
|
|
||||||
import org.springframework.hateoas.ResourceSupport;
|
import org.springframework.hateoas.ResourceSupport;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/")
|
@RequestMapping("/")
|
||||||
public class IndexController {
|
public class IndexController {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET)
|
@GetMapping
|
||||||
public ResourceSupport index() {
|
public ResourceSupport index() {
|
||||||
ResourceSupport index = new ResourceSupport();
|
ResourceSupport index = new ResourceSupport();
|
||||||
index.add(linkTo(CRUDController.class).withRel("crud"));
|
index.add(linkTo(CRUDController.class).withRel("crud"));
|
|
@ -1,4 +1,4 @@
|
||||||
package com.example;
|
package com.baeldung.restdocs;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
@ -17,6 +17,7 @@ public class SecurityConfig {
|
||||||
public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
|
public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
|
||||||
return http.authorizeExchange()
|
return http.authorizeExchange()
|
||||||
.pathMatchers("/admin").hasAuthority("ROLE_ADMIN")
|
.pathMatchers("/admin").hasAuthority("ROLE_ADMIN")
|
||||||
|
.pathMatchers("/actuator/**").permitAll()
|
||||||
.anyExchange().authenticated()
|
.anyExchange().authenticated()
|
||||||
.and().formLogin()
|
.and().formLogin()
|
||||||
.and().build();
|
.and().build();
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
server.port=8081
|
server.port=8081
|
||||||
|
management.endpoints.web.expose=*
|
||||||
|
info.app.name=Spring Boot 2 actuator Application
|
||||||
|
|
||||||
logging.level.root=INFO
|
logging.level.root=INFO
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.actuator;
|
||||||
|
|
||||||
|
import com.baeldung.jsonb.Spring5Application;
|
||||||
|
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.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5Application.class)
|
||||||
|
public class ActuatorInfoIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TestRestTemplate restTemplate;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetInfo_thenReturns200() throws IOException {
|
||||||
|
final ResponseEntity<String> responseEntity = this.restTemplate.getForEntity("/actuator/info", String.class);
|
||||||
|
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFeatures_thenReturns200() throws IOException {
|
||||||
|
final ResponseEntity<String> responseEntity = this.restTemplate.getForEntity("/actuator/features", String.class);
|
||||||
|
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
package com.baeldung.restdocs;
|
||||||
|
|
||||||
|
import com.baeldung.restdocs.CrudInput;
|
||||||
|
import com.baeldung.restdocs.SpringRestDocsApplication;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
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.hateoas.MediaTypes;
|
||||||
|
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||||
|
import org.springframework.restdocs.constraints.ConstraintDescriptions;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||||
|
import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders;
|
||||||
|
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||||
|
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
|
||||||
|
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||||
|
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||||
|
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*;
|
||||||
|
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
||||||
|
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||||
|
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
import static org.springframework.util.StringUtils.collectionToDelimitedString;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = SpringRestDocsApplication.class)
|
||||||
|
public class ApiDocumentationJUnit4IntegrationTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebApplicationContext context;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
|
||||||
|
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||||
|
.apply(documentationConfiguration(this.restDocumentation))
|
||||||
|
.alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void indexExample() throws Exception {
|
||||||
|
this.mockMvc.perform(get("/"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andDo(document("index-example", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), links(linkWithRel("crud").description("The CRUD resource")), responseFields(subsectionWithPath("_links").description("Links to other resources")),
|
||||||
|
responseHeaders(headerWithName("Content-Type").description("The Content-Type of the payload, e.g. `application/hal+json`"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudGetExample() throws Exception {
|
||||||
|
|
||||||
|
Map<String, Object> crud = new HashMap<>();
|
||||||
|
crud.put("id", 1L);
|
||||||
|
crud.put("title", "Sample Model");
|
||||||
|
crud.put("body", "http://www.baeldung.com/");
|
||||||
|
|
||||||
|
String tagLocation = this.mockMvc.perform(get("/crud").contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getHeader("Location");
|
||||||
|
|
||||||
|
crud.put("tags", singletonList(tagLocation));
|
||||||
|
|
||||||
|
ConstraintDescriptions desc = new ConstraintDescriptions(CrudInput.class);
|
||||||
|
|
||||||
|
this.mockMvc.perform(get("/crud").contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andDo(document("crud-get-example", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields(fieldWithPath("id").description("The id of the input" + collectionToDelimitedString(desc.descriptionsForProperty("id"), ". ")),
|
||||||
|
fieldWithPath("title").description("The title of the input"), fieldWithPath("body").description("The body of the input"), fieldWithPath("tags").description("An array of tag resource URIs"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudCreateExample() throws Exception {
|
||||||
|
Map<String, Object> crud = new HashMap<>();
|
||||||
|
crud.put("id", 2L);
|
||||||
|
crud.put("title", "Sample Model");
|
||||||
|
crud.put("body", "http://www.baeldung.com/");
|
||||||
|
|
||||||
|
String tagLocation = this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isCreated())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getHeader("Location");
|
||||||
|
|
||||||
|
crud.put("tags", singletonList(tagLocation));
|
||||||
|
|
||||||
|
this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isCreated())
|
||||||
|
.andDo(document("crud-create-example", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields(fieldWithPath("id").description("The id of the input"), fieldWithPath("title").description("The title of the input"),
|
||||||
|
fieldWithPath("body").description("The body of the input"), fieldWithPath("tags").description("An array of tag resource URIs"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudDeleteExample() throws Exception {
|
||||||
|
this.mockMvc.perform(delete("/crud/{id}", 10))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andDo(document("crud-delete-example", pathParameters(parameterWithName("id").description("The id of the input to delete"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudPatchExample() throws Exception {
|
||||||
|
|
||||||
|
Map<String, String> tag = new HashMap<>();
|
||||||
|
tag.put("name", "PATCH");
|
||||||
|
|
||||||
|
String tagLocation = this.mockMvc.perform(patch("/crud/{id}", 10).contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(tag)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getHeader("Location");
|
||||||
|
|
||||||
|
Map<String, Object> crud = new HashMap<>();
|
||||||
|
crud.put("title", "Sample Model Patch");
|
||||||
|
crud.put("body", "http://www.baeldung.com/");
|
||||||
|
crud.put("tags", singletonList(tagLocation));
|
||||||
|
|
||||||
|
this.mockMvc.perform(patch("/crud/{id}", 10).contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudPutExample() throws Exception {
|
||||||
|
Map<String, String> tag = new HashMap<>();
|
||||||
|
tag.put("name", "PUT");
|
||||||
|
|
||||||
|
String tagLocation = this.mockMvc.perform(put("/crud/{id}", 10).contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(tag)))
|
||||||
|
.andExpect(status().isAccepted())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getHeader("Location");
|
||||||
|
|
||||||
|
Map<String, Object> crud = new HashMap<>();
|
||||||
|
crud.put("title", "Sample Model");
|
||||||
|
crud.put("body", "http://www.baeldung.com/");
|
||||||
|
crud.put("tags", singletonList(tagLocation));
|
||||||
|
|
||||||
|
this.mockMvc.perform(put("/crud/{id}", 10).contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isAccepted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
package com.baeldung.restdocs;
|
||||||
|
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||||
|
import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders;
|
||||||
|
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||||
|
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
|
||||||
|
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||||
|
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||||
|
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*;
|
||||||
|
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
||||||
|
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||||
|
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.*;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
import static org.springframework.util.StringUtils.collectionToDelimitedString;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.hateoas.MediaTypes;
|
||||||
|
import org.springframework.restdocs.RestDocumentationContextProvider;
|
||||||
|
import org.springframework.restdocs.RestDocumentationExtension;
|
||||||
|
import org.springframework.restdocs.constraints.ConstraintDescriptions;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
|
import com.baeldung.restdocs.CrudInput;
|
||||||
|
import com.baeldung.restdocs.SpringRestDocsApplication;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
@ExtendWith({ RestDocumentationExtension.class, SpringExtension.class })
|
||||||
|
@SpringBootTest(classes = SpringRestDocsApplication.class)
|
||||||
|
public class ApiDocumentationJUnit5IntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
|
||||||
|
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
|
||||||
|
.apply(documentationConfiguration(restDocumentation))
|
||||||
|
.alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void indexExample() throws Exception {
|
||||||
|
this.mockMvc.perform(get("/"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andDo(document("index-example", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), links(linkWithRel("crud").description("The CRUD resource")), responseFields(subsectionWithPath("_links").description("Links to other resources")),
|
||||||
|
responseHeaders(headerWithName("Content-Type").description("The Content-Type of the payload, e.g. `application/hal+json`"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudGetExample() throws Exception {
|
||||||
|
|
||||||
|
Map<String, Object> crud = new HashMap<>();
|
||||||
|
crud.put("id", 1L);
|
||||||
|
crud.put("title", "Sample Model");
|
||||||
|
crud.put("body", "http://www.baeldung.com/");
|
||||||
|
|
||||||
|
String tagLocation = this.mockMvc.perform(get("/crud").contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getHeader("Location");
|
||||||
|
|
||||||
|
crud.put("tags", singletonList(tagLocation));
|
||||||
|
|
||||||
|
ConstraintDescriptions desc = new ConstraintDescriptions(CrudInput.class);
|
||||||
|
|
||||||
|
this.mockMvc.perform(get("/crud").contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andDo(document("crud-get-example", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields(fieldWithPath("id").description("The id of the input" + collectionToDelimitedString(desc.descriptionsForProperty("id"), ". ")),
|
||||||
|
fieldWithPath("title").description("The title of the input"), fieldWithPath("body").description("The body of the input"), fieldWithPath("tags").description("An array of tag resource URIs"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudCreateExample() throws Exception {
|
||||||
|
Map<String, Object> crud = new HashMap<>();
|
||||||
|
crud.put("id", 2L);
|
||||||
|
crud.put("title", "Sample Model");
|
||||||
|
crud.put("body", "http://www.baeldung.com/");
|
||||||
|
|
||||||
|
String tagLocation = this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isCreated())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getHeader("Location");
|
||||||
|
|
||||||
|
crud.put("tags", singletonList(tagLocation));
|
||||||
|
|
||||||
|
this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isCreated())
|
||||||
|
.andDo(document("crud-create-example", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields(fieldWithPath("id").description("The id of the input"), fieldWithPath("title").description("The title of the input"),
|
||||||
|
fieldWithPath("body").description("The body of the input"), fieldWithPath("tags").description("An array of tag resource URIs"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudDeleteExample() throws Exception {
|
||||||
|
this.mockMvc.perform(delete("/crud/{id}", 10))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andDo(document("crud-delete-example", pathParameters(parameterWithName("id").description("The id of the input to delete"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudPatchExample() throws Exception {
|
||||||
|
|
||||||
|
Map<String, String> tag = new HashMap<>();
|
||||||
|
tag.put("name", "PATCH");
|
||||||
|
|
||||||
|
String tagLocation = this.mockMvc.perform(patch("/crud/{id}", 10).contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(tag)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getHeader("Location");
|
||||||
|
|
||||||
|
Map<String, Object> crud = new HashMap<>();
|
||||||
|
crud.put("title", "Sample Model Patch");
|
||||||
|
crud.put("body", "http://www.baeldung.com/");
|
||||||
|
crud.put("tags", singletonList(tagLocation));
|
||||||
|
|
||||||
|
this.mockMvc.perform(patch("/crud/{id}", 10).contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void crudPutExample() throws Exception {
|
||||||
|
Map<String, String> tag = new HashMap<>();
|
||||||
|
tag.put("name", "PUT");
|
||||||
|
|
||||||
|
String tagLocation = this.mockMvc.perform(put("/crud/{id}", 10).contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(tag)))
|
||||||
|
.andExpect(status().isAccepted())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getHeader("Location");
|
||||||
|
|
||||||
|
Map<String, Object> crud = new HashMap<>();
|
||||||
|
crud.put("title", "Sample Model");
|
||||||
|
crud.put("body", "http://www.baeldung.com/");
|
||||||
|
crud.put("tags", singletonList(tagLocation));
|
||||||
|
|
||||||
|
this.mockMvc.perform(put("/crud/{id}", 10).contentType(MediaTypes.HAL_JSON)
|
||||||
|
.content(this.objectMapper.writeValueAsString(crud)))
|
||||||
|
.andExpect(status().isAccepted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
|
|
@ -0,0 +1,227 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Maven2 Start Up Batch script
|
||||||
|
#
|
||||||
|
# Required ENV vars:
|
||||||
|
# ------------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# M2_HOME - location of maven2's installed home dir
|
||||||
|
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
# e.g. to debug Maven itself, use
|
||||||
|
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||||
|
|
||||||
|
if [ -f /etc/mavenrc ] ; then
|
||||||
|
. /etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$HOME/.mavenrc" ] ; then
|
||||||
|
. "$HOME/.mavenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OS specific support. $var _must_ be set to either true or false.
|
||||||
|
cygwin=false;
|
||||||
|
darwin=false;
|
||||||
|
mingw=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN*) cygwin=true ;;
|
||||||
|
MINGW*) mingw=true;;
|
||||||
|
Darwin*) darwin=true
|
||||||
|
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||||
|
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
if [ -x "/usr/libexec/java_home" ]; then
|
||||||
|
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||||
|
else
|
||||||
|
export JAVA_HOME="/Library/Java/Home"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
if [ -r /etc/gentoo-release ] ; then
|
||||||
|
JAVA_HOME=`java-config --jre-home`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$M2_HOME" ] ; then
|
||||||
|
## resolve links - $0 may be a link to maven's home
|
||||||
|
PRG="$0"
|
||||||
|
|
||||||
|
# need this for relative symlinks
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG="`dirname "$PRG"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
saveddir=`pwd`
|
||||||
|
|
||||||
|
M2_HOME=`dirname "$PRG"`/..
|
||||||
|
|
||||||
|
# make it fully qualified
|
||||||
|
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||||
|
|
||||||
|
cd "$saveddir"
|
||||||
|
# echo Using m2 at $M2_HOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $mingw ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||||
|
# TODO classpath?
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
javaExecutable="`which javac`"
|
||||||
|
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||||
|
# readlink(1) is not available as standard on Solaris 10.
|
||||||
|
readLink=`which readlink`
|
||||||
|
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||||
|
if $darwin ; then
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||||
|
else
|
||||||
|
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||||
|
fi
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||||
|
JAVA_HOME="$javaHome"
|
||||||
|
export JAVA_HOME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVACMD" ] ; then
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="`which java`"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||||
|
echo " We cannot execute $JAVACMD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
echo "Warning: JAVA_HOME environment variable is not set."
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||||
|
|
||||||
|
# traverses directory structure from process work directory to filesystem root
|
||||||
|
# first directory with .mvn subdirectory is considered project base directory
|
||||||
|
find_maven_basedir() {
|
||||||
|
|
||||||
|
if [ -z "$1" ]
|
||||||
|
then
|
||||||
|
echo "Path not specified to find_maven_basedir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
basedir="$1"
|
||||||
|
wdir="$1"
|
||||||
|
while [ "$wdir" != '/' ] ; do
|
||||||
|
if [ -d "$wdir"/.mvn ] ; then
|
||||||
|
basedir=$wdir
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||||
|
if [ -d "${wdir}" ]; then
|
||||||
|
wdir=`cd "$wdir/.."; pwd`
|
||||||
|
fi
|
||||||
|
# end of workaround
|
||||||
|
done
|
||||||
|
echo "${basedir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# concatenates all lines of a file
|
||||||
|
concat_lines() {
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
echo "$(tr -s '\n' ' ' < "$1")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||||
|
if [ -z "$BASE_DIR" ]; then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo $MAVEN_PROJECTBASEDIR
|
||||||
|
fi
|
||||||
|
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||||
|
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||||
|
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
exec "$JAVACMD" \
|
||||||
|
$MAVEN_OPTS \
|
||||||
|
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||||
|
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||||
|
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
@ -0,0 +1,145 @@
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
@REM or more contributor license agreements. See the NOTICE file
|
||||||
|
@REM distributed with this work for additional information
|
||||||
|
@REM regarding copyright ownership. The ASF licenses this file
|
||||||
|
@REM to you under the Apache License, Version 2.0 (the
|
||||||
|
@REM "License"); you may not use this file except in compliance
|
||||||
|
@REM with the License. You may obtain a copy of the License at
|
||||||
|
@REM
|
||||||
|
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@REM
|
||||||
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
|
@REM software distributed under the License is distributed on an
|
||||||
|
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
@REM KIND, either express or implied. See the License for the
|
||||||
|
@REM specific language governing permissions and limitations
|
||||||
|
@REM under the License.
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Maven2 Start Up Batch script
|
||||||
|
@REM
|
||||||
|
@REM Required ENV vars:
|
||||||
|
@REM JAVA_HOME - location of a JDK home dir
|
||||||
|
@REM
|
||||||
|
@REM Optional ENV vars
|
||||||
|
@REM M2_HOME - location of maven2's installed home dir
|
||||||
|
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||||
|
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||||
|
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
@REM e.g. to debug Maven itself, use
|
||||||
|
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||||
|
@echo off
|
||||||
|
@REM set title of command window
|
||||||
|
title %0
|
||||||
|
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||||
|
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||||
|
|
||||||
|
@REM set %HOME% to equivalent of $HOME
|
||||||
|
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||||
|
|
||||||
|
@REM Execute a user defined script before this one
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||||
|
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||||
|
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||||
|
:skipRcPre
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
set ERROR_CODE=0
|
||||||
|
|
||||||
|
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
@REM ==== START VALIDATION ====
|
||||||
|
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME not found in your environment. >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
:OkJHome
|
||||||
|
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||||
|
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
@REM ==== END VALIDATION ====
|
||||||
|
|
||||||
|
:init
|
||||||
|
|
||||||
|
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||||
|
@REM Fallback to current working directory if not found.
|
||||||
|
|
||||||
|
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||||
|
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||||
|
|
||||||
|
set EXEC_DIR=%CD%
|
||||||
|
set WDIR=%EXEC_DIR%
|
||||||
|
:findBaseDir
|
||||||
|
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||||
|
cd ..
|
||||||
|
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||||
|
set WDIR=%CD%
|
||||||
|
goto findBaseDir
|
||||||
|
|
||||||
|
:baseDirFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
goto endDetectBaseDir
|
||||||
|
|
||||||
|
:baseDirNotFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
|
||||||
|
:endDetectBaseDir
|
||||||
|
|
||||||
|
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||||
|
|
||||||
|
@setlocal EnableExtensions EnableDelayedExpansion
|
||||||
|
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||||
|
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||||
|
|
||||||
|
:endReadAdditionalConfig
|
||||||
|
|
||||||
|
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||||
|
|
||||||
|
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||||
|
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||||
|
if ERRORLEVEL 1 goto error
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
set ERROR_CODE=1
|
||||||
|
|
||||||
|
:end
|
||||||
|
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||||
|
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||||
|
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||||
|
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||||
|
:skipRcPost
|
||||||
|
|
||||||
|
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||||
|
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||||
|
|
||||||
|
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||||
|
|
||||||
|
exit /B %ERROR_CODE%
|
|
@ -1,5 +0,0 @@
|
||||||
###The Course
|
|
||||||
The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|
||||||
|
|
||||||
###Relevant Articles:
|
|
||||||
- [Introduction to Spring REST Docs](http://www.baeldung.com/spring-rest-docs)
|
|
|
@ -1,112 +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.example</groupId>
|
|
||||||
<artifactId>spring-rest-docs</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<name>spring-rest-docs</name>
|
|
||||||
<description>Demo project for Spring Boot</description>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<artifactId>parent-boot-5</artifactId>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<relativePath>../parent-boot-5</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
|
||||||
<restdocs.version>1.1.2.RELEASE</restdocs.version>
|
|
||||||
<jsonpath.version>2.2.0</jsonpath.version>
|
|
||||||
<asciidoctor-plugin.version>1.5.3</asciidoctor-plugin.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.restdocs</groupId>
|
|
||||||
<artifactId>spring-restdocs-mockmvc</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.jayway.jsonpath</groupId>
|
|
||||||
<artifactId>json-path</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.asciidoctor</groupId>
|
|
||||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
|
||||||
<version>${asciidoctor-plugin.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>generate-docs</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>process-asciidoc</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<backend>html</backend>
|
|
||||||
<doctype>book</doctype>
|
|
||||||
<attributes>
|
|
||||||
<snippets>${snippetsDirectory}</snippets>
|
|
||||||
</attributes>
|
|
||||||
<sourceDirectory>src/docs/asciidocs</sourceDirectory>
|
|
||||||
<outputDirectory>target/generated-docs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>integration</id>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>test</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/*LiveTest.java</exclude>
|
|
||||||
</excludes>
|
|
||||||
<includes>
|
|
||||||
<include>**/*IntegrationTest.java</include>
|
|
||||||
</includes>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<test.mime>json</test.mime>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,41 +0,0 @@
|
||||||
package com.example;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.validator.constraints.NotBlank;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
|
|
||||||
public class CrudInput {
|
|
||||||
|
|
||||||
// @NotBlank
|
|
||||||
private final String title;
|
|
||||||
|
|
||||||
private final String body;
|
|
||||||
|
|
||||||
private final List<URI> tagUris;
|
|
||||||
|
|
||||||
@JsonCreator
|
|
||||||
public CrudInput(@JsonProperty("title") String title, @JsonProperty("body") String body, @JsonProperty("tags") List<URI> tagUris) {
|
|
||||||
this.title = title;
|
|
||||||
this.body = body;
|
|
||||||
this.tagUris = tagUris == null ? Collections.<URI> emptyList() : tagUris;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBody() {
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty("tags")
|
|
||||||
public List<URI> getTagUris() {
|
|
||||||
return this.tagUris;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,181 +0,0 @@
|
||||||
package com.example;
|
|
||||||
|
|
||||||
import static java.util.Collections.singletonList;
|
|
||||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
|
||||||
import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders;
|
|
||||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
|
||||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
|
|
||||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
|
||||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
|
||||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
|
|
||||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
|
||||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch;
|
|
||||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
|
|
||||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put;
|
|
||||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
|
||||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
|
||||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
|
||||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
|
||||||
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
|
|
||||||
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
|
|
||||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
||||||
import static org.springframework.util.StringUtils.collectionToDelimitedString;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Rule;
|
|
||||||
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.hateoas.MediaTypes;
|
|
||||||
import org.springframework.restdocs.RestDocumentation;
|
|
||||||
import org.springframework.restdocs.constraints.ConstraintDescriptions;
|
|
||||||
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
|
|
||||||
import org.springframework.restdocs.payload.FieldDescriptor;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
@SpringBootTest(classes = SpringRestDocsApplication.class)
|
|
||||||
@WebAppConfiguration
|
|
||||||
public class ApiDocumentationIntegrationTest {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public final RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WebApplicationContext context;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
private RestDocumentationResultHandler document;
|
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
this.document = document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()));
|
|
||||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).apply(documentationConfiguration(this.restDocumentation)).alwaysDo(this.document).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void headersExample() throws Exception {
|
|
||||||
this.document.snippets(responseHeaders(headerWithName("Content-Type").description("The Content-Type of the payload, e.g. `application/hal+json`")));
|
|
||||||
this.mockMvc.perform(get("/")).andExpect(status().isOk());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void indexExample() throws Exception {
|
|
||||||
this.document.snippets(links(linkWithRel("crud").description("The <<resources-tags,Tags resource>>")), responseFields(fieldWithPath("_links").description("<<resources-index-links,Links>> to other resources")));
|
|
||||||
this.mockMvc.perform(get("/")).andExpect(status().isOk());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void crudGetExample() throws Exception {
|
|
||||||
|
|
||||||
Map<String, String> tag = new HashMap<>();
|
|
||||||
tag.put("name", "GET");
|
|
||||||
|
|
||||||
String tagLocation = this.mockMvc.perform(get("/crud").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isOk()).andReturn().getResponse().getHeader("Location");
|
|
||||||
|
|
||||||
Map<String, Object> crud = new HashMap<>();
|
|
||||||
crud.put("title", "Sample Model");
|
|
||||||
crud.put("body", "http://www.baeldung.com/");
|
|
||||||
crud.put("tags", singletonList(tagLocation));
|
|
||||||
|
|
||||||
this.mockMvc.perform(get("/crud").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isOk());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void crudCreateExample() throws Exception {
|
|
||||||
Map<String, String> tag = new HashMap<>();
|
|
||||||
tag.put("name", "CREATE");
|
|
||||||
|
|
||||||
String tagLocation = this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isCreated()).andReturn().getResponse().getHeader("Location");
|
|
||||||
|
|
||||||
Map<String, Object> crud = new HashMap<>();
|
|
||||||
crud.put("title", "Sample Model");
|
|
||||||
crud.put("body", "http://www.baeldung.com/");
|
|
||||||
crud.put("tags", singletonList(tagLocation));
|
|
||||||
|
|
||||||
ConstrainedFields fields = new ConstrainedFields(CrudInput.class);
|
|
||||||
this.document.snippets(requestFields(fields.withPath("title").description("The title of the note"), fields.withPath("body").description("The body of the note"), fields.withPath("tags").description("An array of tag resource URIs")));
|
|
||||||
this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isCreated());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void crudDeleteExample() throws Exception {
|
|
||||||
|
|
||||||
Map<String, String> tag = new HashMap<>();
|
|
||||||
tag.put("name", "DELETE");
|
|
||||||
|
|
||||||
String tagLocation = this.mockMvc.perform(delete("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isOk()).andReturn().getResponse().getHeader("Location");
|
|
||||||
|
|
||||||
Map<String, Object> crud = new HashMap<>();
|
|
||||||
crud.put("title", "Sample Model");
|
|
||||||
crud.put("body", "http://www.baeldung.com/");
|
|
||||||
crud.put("tags", singletonList(tagLocation));
|
|
||||||
|
|
||||||
this.mockMvc.perform(delete("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isOk());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void crudPatchExample() throws Exception {
|
|
||||||
|
|
||||||
Map<String, String> tag = new HashMap<>();
|
|
||||||
tag.put("name", "PATCH");
|
|
||||||
|
|
||||||
String tagLocation = this.mockMvc.perform(patch("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isNoContent()).andReturn().getResponse().getHeader("Location");
|
|
||||||
|
|
||||||
Map<String, Object> crud = new HashMap<>();
|
|
||||||
crud.put("title", "Sample Model");
|
|
||||||
crud.put("body", "http://www.baeldung.com/");
|
|
||||||
crud.put("tags", singletonList(tagLocation));
|
|
||||||
|
|
||||||
this.mockMvc.perform(patch("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isNoContent());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void crudPutExample() throws Exception {
|
|
||||||
Map<String, String> tag = new HashMap<>();
|
|
||||||
tag.put("name", "PUT");
|
|
||||||
|
|
||||||
String tagLocation = this.mockMvc.perform(put("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isAccepted()).andReturn().getResponse().getHeader("Location");
|
|
||||||
|
|
||||||
Map<String, Object> crud = new HashMap<>();
|
|
||||||
crud.put("title", "Sample Model");
|
|
||||||
crud.put("body", "http://www.baeldung.com/");
|
|
||||||
crud.put("tags", singletonList(tagLocation));
|
|
||||||
|
|
||||||
this.mockMvc.perform(put("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isAccepted());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void contextLoads() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ConstrainedFields {
|
|
||||||
|
|
||||||
private final ConstraintDescriptions constraintDescriptions;
|
|
||||||
|
|
||||||
ConstrainedFields(Class<?> input) {
|
|
||||||
this.constraintDescriptions = new ConstraintDescriptions(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FieldDescriptor withPath(String path) {
|
|
||||||
return fieldWithPath(path).attributes(key("constraints").value(collectionToDelimitedString(this.constraintDescriptions.descriptionsForProperty(path), ". ")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
package com.example;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
import static org.hamcrest.Matchers.notNullValue;
|
|
||||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
|
||||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
|
||||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
|
||||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
|
||||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
|
||||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Rule;
|
|
||||||
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.hateoas.MediaTypes;
|
|
||||||
import org.springframework.restdocs.RestDocumentation;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
@SpringBootTest(classes = SpringRestDocsApplication.class)
|
|
||||||
@WebAppConfiguration
|
|
||||||
public class GettingStartedDocumentationIntegrationTest {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public final RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WebApplicationContext context;
|
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).apply(documentationConfiguration(this.restDocumentation)).alwaysDo(document("{method-name}/{step}/", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()))).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void index() throws Exception {
|
|
||||||
this.mockMvc.perform(get("/").accept(MediaTypes.HAL_JSON)).andExpect(status().isOk()).andExpect(jsonPath("_links.crud", is(notNullValue()))).andExpect(jsonPath("_links.crud", is(notNullValue())));
|
|
||||||
}
|
|
||||||
|
|
||||||
// String createNote() throws Exception {
|
|
||||||
// Map<String, String> note = new HashMap<String, String>();
|
|
||||||
// note.put("title", "Note creation with cURL");
|
|
||||||
// note.put("body", "An example of how to create a note using curl");
|
|
||||||
// String noteLocation = this.mockMvc.perform(post("/crud")
|
|
||||||
// .contentType(MediaTypes.HAL_JSON)
|
|
||||||
// .content(objectMapper.writeValueAsString(note)))
|
|
||||||
// .andExpect(status().isCreated())
|
|
||||||
// .andExpect(header().string("Location", notNullValue()))
|
|
||||||
// .andReturn()
|
|
||||||
// .getResponse()
|
|
||||||
// .getHeader("Location");
|
|
||||||
// return noteLocation;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// MvcResult getNote(String noteLocation) throws Exception {
|
|
||||||
// return this.mockMvc.perform(get(noteLocation))
|
|
||||||
// .andExpect(status().isOk())
|
|
||||||
// .andExpect(jsonPath("title", is(notNullValue())))
|
|
||||||
// .andExpect(jsonPath("body", is(notNullValue())))
|
|
||||||
// .andExpect(jsonPath("_links.crud", is(notNullValue())))
|
|
||||||
// .andReturn();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// String createTag() throws Exception, JsonProcessingException {
|
|
||||||
// Map<String, String> tag = new HashMap<String, String>();
|
|
||||||
// tag.put("name", "getting-started");
|
|
||||||
// String tagLocation = this.mockMvc.perform(post("/crud")
|
|
||||||
// .contentType(MediaTypes.HAL_JSON)
|
|
||||||
// .content(objectMapper.writeValueAsString(tag)))
|
|
||||||
// .andExpect(status().isCreated())
|
|
||||||
// .andExpect(header().string("Location", notNullValue()))
|
|
||||||
// .andReturn()
|
|
||||||
// .getResponse()
|
|
||||||
// .getHeader("Location");
|
|
||||||
// return tagLocation;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void getTag(String tagLocation) throws Exception {
|
|
||||||
// this.mockMvc.perform(get(tagLocation)).andExpect(status().isOk())
|
|
||||||
// .andExpect(jsonPath("name", is(notNullValue())))
|
|
||||||
// .andExpect(jsonPath("_links.tagged-notes", is(notNullValue())));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// String createTaggedNote(String tag) throws Exception {
|
|
||||||
// Map<String, Object> note = new HashMap<String, Object>();
|
|
||||||
// note.put("title", "Tagged note creation with cURL");
|
|
||||||
// note.put("body", "An example of how to create a tagged note using cURL");
|
|
||||||
// note.put("tags", Arrays.asList(tag));
|
|
||||||
//
|
|
||||||
// String noteLocation = this.mockMvc.perform(post("/notes")
|
|
||||||
// .contentType(MediaTypes.HAL_JSON)
|
|
||||||
// .content(objectMapper.writeValueAsString(note)))
|
|
||||||
// .andExpect(status().isCreated())
|
|
||||||
// .andExpect(header().string("Location", notNullValue()))
|
|
||||||
// .andReturn()
|
|
||||||
// .getResponse()
|
|
||||||
// .getHeader("Location");
|
|
||||||
// return noteLocation;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void getTags(String noteTagsLocation) throws Exception {
|
|
||||||
// this.mockMvc.perform(get(noteTagsLocation))
|
|
||||||
// .andExpect(status().isOk())
|
|
||||||
// .andExpect(jsonPath("_embedded.tags", hasSize(1)));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void tagExistingNote(String noteLocation, String tagLocation) throws Exception {
|
|
||||||
// Map<String, Object> update = new HashMap<String, Object>();
|
|
||||||
// update.put("tags", Arrays.asList(tagLocation));
|
|
||||||
// this.mockMvc.perform(patch(noteLocation)
|
|
||||||
// .contentType(MediaTypes.HAL_JSON)
|
|
||||||
// .content(objectMapper.writeValueAsString(update)))
|
|
||||||
// .andExpect(status().isNoContent());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// MvcResult getTaggedExistingNote(String noteLocation) throws Exception {
|
|
||||||
// return this.mockMvc.perform(get(noteLocation)).andExpect(status().isOk()).andReturn();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void getTagsForExistingNote(String noteTagsLocation) throws Exception {
|
|
||||||
// this.mockMvc.perform(get(noteTagsLocation))
|
|
||||||
// .andExpect(status().isOk()).andExpect(jsonPath("_embedded.tags", hasSize(1)));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private String getLink(MvcResult result, String rel)
|
|
||||||
// throws UnsupportedEncodingException {
|
|
||||||
// return JsonPath.parse(result.getResponse().getContentAsString()).read("_links." + rel + ".href");
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
|
@ -8,3 +8,5 @@
|
||||||
- [Introduction to Vavr’s Validation API](http://www.baeldung.com/vavr-validation-api)
|
- [Introduction to Vavr’s Validation API](http://www.baeldung.com/vavr-validation-api)
|
||||||
- [Guide to Collections API in Vavr](http://www.baeldung.com/vavr-collections)
|
- [Guide to Collections API in Vavr](http://www.baeldung.com/vavr-collections)
|
||||||
- [Collection Factory Methods for Vavr](http://www.baeldung.com/vavr-collection-factory-methods)
|
- [Collection Factory Methods for Vavr](http://www.baeldung.com/vavr-collection-factory-methods)
|
||||||
|
- [Introduction to Future in Vavr](http://www.baeldung.com/vavr-future)
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,14 @@ public class FutureTest {
|
||||||
.isEqualTo(HELLO);
|
.isEqualTo(HELLO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenTransform_thenCorrect() {
|
||||||
|
Future<Object> future = Future.of(() -> 5)
|
||||||
|
.transformValue(result -> Try.of(() -> HELLO + result.get()));
|
||||||
|
|
||||||
|
assertThat(future.get()).isEqualTo(HELLO + 5);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenChainingCallbacks_thenCorrect() {
|
public void whenChainingCallbacks_thenCorrect() {
|
||||||
Future.of(() -> HELLO)
|
Future.of(() -> HELLO)
|
||||||
|
@ -140,6 +148,14 @@ public class FutureTest {
|
||||||
.isEqualTo("Hello from Baeldung");
|
.isEqualTo("Hello from Baeldung");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCallFlatMap_thenCorrect() {
|
||||||
|
Future<Object> futureMap = Future.of(() -> 1)
|
||||||
|
.flatMap((i) -> Future.of(() -> "Hello: " + i));
|
||||||
|
|
||||||
|
assertThat(futureMap.get()).isEqualTo("Hello: 1");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenFutureFails_thenGetErrorMessage() {
|
public void whenFutureFails_thenGetErrorMessage() {
|
||||||
Future<String> future = Future.of(() -> "Hello".substring(-1))
|
Future<String> future = Future.of(() -> "Hello".substring(-1))
|
||||||
|
|
Loading…
Reference in New Issue