Skip to content

Commit 563f74a

Browse files
harshavsKevinGilmore
authored andcommitted
[BAEL-3319] - Documenting a Spring REST API using OpenAPI (eugenp#7919)
* [BAEL-3211] Generate Integers within a range in Java * [BAEL-3211] Generate Integers within a range in Java * Moved files from java-numbers to java-numbers-2 * [BAEL-3319] - Documenting a Spring REST API using OpenAPI * [BAEL-3319] Added a new module for springdoc-openapi library * Incorporated feedback - indents, GetMapping et al annotations, package as jar, remove README & spring-webflux change, use of map in BookRepository * Used DeleteMapping instead of RequestMapping * Add the spring-boot-springdoc module to root pom.xml * Remove plain spring boot starter from pom.xml
1 parent d28f71d commit 563f74a

File tree

11 files changed

+338
-2
lines changed

11 files changed

+338
-2
lines changed

pom.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,10 +722,11 @@
722722
<module>spring-boot-parent</module>
723723
<module>spring-boot-property-exp</module>
724724
<module>spring-boot-security</module>
725+
<module>spring-boot-springdoc</module>
725726
<module>spring-boot-testing</module>
726727
<module>spring-boot-vue</module>
727728
<module>spring-caching</module>
728-
<module>spring-boot-libraries</module>
729+
<module>spring-boot-libraries</module>
729730

730731

731732
<module>spring-cloud</module>
@@ -922,6 +923,7 @@
922923
<module>spring-boot-keycloak</module>
923924
<module>spring-boot-mvc</module>
924925
<module>spring-boot-property-exp</module>
926+
<module>spring-boot-springdoc</module>
925927
<module>spring-boot-vue</module>
926928
<module>spring-cloud</module>
927929
<module>spring-cloud/spring-cloud-archaius/basic-config</module>
@@ -1467,8 +1469,9 @@
14671469
<module>spring-boot-parent</module>
14681470
<module>spring-boot-property-exp</module>
14691471
<module>spring-boot-security</module>
1472+
<module>spring-boot-springdoc</module>
14701473
<module>spring-boot-vue</module>
1471-
<module>spring-caching</module>
1474+
<module>spring-caching</module>
14721475
<module>spring-cloud</module>
14731476
<module>spring-cloud-bus</module>
14741477
<!-- <module>spring-cloud-cli</module> --> <!-- Not a maven project -->

spring-boot-springdoc/pom.xml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<groupId>com.baeldung</groupId>
7+
<artifactId>spring-boot-springdoc</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
<name>spring-boot-springdoc</name>
10+
<description>Project for Springdoc integration</description>
11+
<packaging>jar</packaging>
12+
13+
<parent>
14+
<artifactId>parent-boot-2</artifactId>
15+
<groupId>com.baeldung</groupId>
16+
<version>0.0.1-SNAPSHOT</version>
17+
<relativePath>../parent-boot-2</relativePath>
18+
</parent>
19+
20+
<properties>
21+
<java.version>1.8</java.version>
22+
</properties>
23+
24+
<dependencies>
25+
<dependency>
26+
<groupId>org.springframework.boot</groupId>
27+
<artifactId>spring-boot-starter-web</artifactId>
28+
</dependency>
29+
30+
<dependency>
31+
<groupId>org.springframework.boot</groupId>
32+
<artifactId>spring-boot-starter-test</artifactId>
33+
<scope>test</scope>
34+
</dependency>
35+
36+
<!-- SpringDoc -->
37+
<dependency>
38+
<groupId>org.springdoc</groupId>
39+
<artifactId>springdoc-openapi-core</artifactId>
40+
<version>1.1.45</version>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.springdoc</groupId>
44+
<artifactId>springdoc-openapi-ui</artifactId>
45+
<version>1.1.45</version>
46+
</dependency>
47+
</dependencies>
48+
49+
<build>
50+
<plugins>
51+
<plugin>
52+
<groupId>org.springframework.boot</groupId>
53+
<artifactId>spring-boot-maven-plugin</artifactId>
54+
</plugin>
55+
</plugins>
56+
</build>
57+
58+
<profiles>
59+
<profile>
60+
<id>integration</id>
61+
<build>
62+
<plugins>
63+
<plugin>
64+
<groupId>org.springframework.boot</groupId>
65+
<artifactId>spring-boot-maven-plugin</artifactId>
66+
<version>2.1.8.RELEASE</version>
67+
<executions>
68+
<execution>
69+
<id>pre-integration-test</id>
70+
<goals>
71+
<goal>start</goal>
72+
</goals>
73+
</execution>
74+
<execution>
75+
<id>post-integration-test</id>
76+
<goals>
77+
<goal>stop</goal>
78+
</goals>
79+
</execution>
80+
</executions>
81+
</plugin>
82+
<plugin>
83+
<groupId>org.springdoc</groupId>
84+
<artifactId>springdoc-openapi-maven-plugin</artifactId>
85+
<version>0.2</version>
86+
<executions>
87+
<execution>
88+
<phase>integration-test</phase>
89+
<goals>
90+
<goal>generate</goal>
91+
</goals>
92+
</execution>
93+
</executions>
94+
<configuration>
95+
<apiDocsUrl>http://localhost:8080/api-docs</apiDocsUrl>
96+
<outputFileName>openapi.json</outputFileName>
97+
<outputDir>${project.build.directory}</outputDir>
98+
</configuration>
99+
</plugin>
100+
</plugins>
101+
</build>
102+
</profile>
103+
</profiles>
104+
105+
106+
</project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.baeldung.springdoc;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class SpringdocApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(SpringdocApplication.class, args);
11+
}
12+
13+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.baeldung.springdoc.controller;
2+
3+
import java.util.Collection;
4+
5+
import javax.validation.Valid;
6+
import javax.validation.constraints.NotNull;
7+
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.http.HttpStatus;
10+
import org.springframework.web.bind.annotation.DeleteMapping;
11+
import org.springframework.web.bind.annotation.GetMapping;
12+
import org.springframework.web.bind.annotation.PatchMapping;
13+
import org.springframework.web.bind.annotation.PathVariable;
14+
import org.springframework.web.bind.annotation.PostMapping;
15+
import org.springframework.web.bind.annotation.PutMapping;
16+
import org.springframework.web.bind.annotation.RequestBody;
17+
import org.springframework.web.bind.annotation.RequestMapping;
18+
import org.springframework.web.bind.annotation.RequestMethod;
19+
import org.springframework.web.bind.annotation.ResponseStatus;
20+
import org.springframework.web.bind.annotation.RestController;
21+
22+
import com.baeldung.springdoc.exception.BookNotFoundException;
23+
import com.baeldung.springdoc.model.Book;
24+
import com.baeldung.springdoc.repository.BookRepository;
25+
26+
@RestController
27+
@RequestMapping("/api/book")
28+
public class BookController {
29+
30+
@Autowired
31+
private BookRepository repository;
32+
33+
@GetMapping("/{id}")
34+
public Book findById(@PathVariable long id) {
35+
return repository.findById(id)
36+
.orElseThrow(() -> new BookNotFoundException());
37+
}
38+
39+
@GetMapping("/")
40+
public Collection<Book> findBooks() {
41+
return repository.getBooks();
42+
}
43+
44+
@PutMapping("/{id}")
45+
@ResponseStatus(HttpStatus.OK)
46+
public Book updateBook(@PathVariable("id") final String id, @RequestBody final Book book) {
47+
return book;
48+
}
49+
50+
@PatchMapping("/{id}")
51+
@ResponseStatus(HttpStatus.OK)
52+
public Book patchBook(@PathVariable("id") final String id, @RequestBody final Book book) {
53+
return book;
54+
}
55+
56+
@PostMapping("/")
57+
@ResponseStatus(HttpStatus.CREATED)
58+
public Book postBook(@NotNull @Valid @RequestBody final Book book) {
59+
return book;
60+
}
61+
62+
@RequestMapping(method = RequestMethod.HEAD, value = "/")
63+
@ResponseStatus(HttpStatus.OK)
64+
public Book headBook() {
65+
return new Book();
66+
}
67+
68+
@DeleteMapping("/{id}")
69+
@ResponseStatus(HttpStatus.OK)
70+
public long deleteBook(@PathVariable final long id) {
71+
return id;
72+
}
73+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.baeldung.springdoc.exception;
2+
3+
@SuppressWarnings("serial")
4+
public class BookNotFoundException extends RuntimeException {
5+
6+
public BookNotFoundException() {
7+
8+
}
9+
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.baeldung.springdoc.exception;
2+
3+
import org.springframework.core.convert.ConversionFailedException;
4+
import org.springframework.http.HttpStatus;
5+
import org.springframework.http.ResponseEntity;
6+
import org.springframework.web.bind.annotation.ExceptionHandler;
7+
import org.springframework.web.bind.annotation.ResponseStatus;
8+
import org.springframework.web.bind.annotation.RestControllerAdvice;
9+
10+
@RestControllerAdvice
11+
public class GlobalControllerExceptionHandler {
12+
13+
@ExceptionHandler(ConversionFailedException.class)
14+
@ResponseStatus(HttpStatus.BAD_REQUEST)
15+
public ResponseEntity<String> handleConnversion(RuntimeException ex) {
16+
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
17+
}
18+
19+
@ExceptionHandler(BookNotFoundException.class)
20+
@ResponseStatus(HttpStatus.NOT_FOUND)
21+
public ResponseEntity<String> handleBookNotFound(RuntimeException ex) {
22+
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
23+
}
24+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.baeldung.springdoc.model;
2+
3+
import javax.validation.constraints.NotBlank;
4+
import javax.validation.constraints.Size;
5+
6+
public class Book {
7+
8+
private long id;
9+
10+
@NotBlank
11+
@Size(min = 0, max = 20)
12+
private String title;
13+
14+
@NotBlank
15+
@Size(min = 0, max = 30)
16+
private String author;
17+
18+
public long getId() {
19+
return id;
20+
}
21+
22+
public void setId(long id) {
23+
this.id = id;
24+
}
25+
26+
public String getTitle() {
27+
return title;
28+
}
29+
30+
public void setTitle(String title) {
31+
this.title = title;
32+
}
33+
34+
public String getAuthor() {
35+
return author;
36+
}
37+
38+
public void setAuthor(String author) {
39+
this.author = author;
40+
}
41+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.baeldung.springdoc.repository;
2+
3+
import java.util.Collection;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
import java.util.Optional;
7+
8+
import org.springframework.stereotype.Repository;
9+
10+
import com.baeldung.springdoc.model.Book;
11+
12+
@Repository
13+
public class BookRepository {
14+
15+
private Map<Long, Book> books = new HashMap<>();
16+
17+
public Optional<Book> findById(long id) {
18+
return Optional.ofNullable(books.get(id));
19+
}
20+
21+
public void add(Book book) {
22+
books.put(book.getId(), book);
23+
}
24+
25+
public Collection<Book> getBooks() {
26+
return books.values();
27+
}
28+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# custom path for swagger-ui
2+
springdoc.swagger-ui.path=/swagger-ui-custom.html
3+
4+
# custom path for api docs
5+
springdoc.api-docs.path=/api-docs
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<configuration>
3+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
4+
<encoder>
5+
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
6+
</pattern>
7+
</encoder>
8+
</appender>
9+
10+
<logger name="org.springframework" level="DEBUG" />
11+
<logger name="org.springframework.transaction" level="WARN" />
12+
13+
<root level="INFO">
14+
<appender-ref ref="STDOUT" />
15+
</root>
16+
</configuration>

0 commit comments

Comments
 (0)