├── .gitignore
├── .travis.yml
├── README.md
├── app-build-deploy.bat
├── pom.xml
├── src
└── main
│ ├── java
│ └── com
│ │ └── kaluzny
│ │ ├── Application.java
│ │ ├── domain
│ │ ├── Book.java
│ │ └── BookRepository.java
│ │ └── web
│ │ └── BookRestController.java
│ └── resources
│ ├── Request.http
│ ├── application.yml
│ └── body.json
└── travis-ci.bat
/.gitignore:
--------------------------------------------------------------------------------
1 | # Maven
2 | target
3 |
4 | # Eclipse
5 | .project
6 | .settings
7 | .classpath
8 |
9 | # IntelliJ IDEA
10 | .idea
11 | *.iml
12 |
13 | /app-build-deploy.bat
14 | /travis-ci.bat
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | jdk:
4 | oraclejdk8
5 | dist: trusty
6 | sudo:
7 | required
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Plain REST API CRUD with Spring Boot 3 and PostgreSQL.
2 |
3 | [](https://travis-ci.org/OKaluzny/spring-boot-rest-api-postgresql)
4 |
5 | ### Technology stack:
6 |
7 | * Spring Boot 3;
8 | * Spring Web;
9 | * Spring Data;
10 | * PostgreSQL database;
11 | * Hibernate;
12 | * Lombok;
13 | * Spring Security (as basic authentication).
14 |
15 | #### To run this application use:
16 |
17 | ```bash
18 | mvn spring-boot:run
19 | ```
20 |
21 | ### The view in the Postman:
22 | [http://localhost:8080/api/books](http://localhost:8080/api/books)
23 |
--------------------------------------------------------------------------------
/app-build-deploy.bat:
--------------------------------------------------------------------------------
1 | mvn spring-boot:run
2 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.kaluzny
7 | spring-boot2-rest-api-postgresql
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 |
12 | UTF-8
13 | ${project.encoding}
14 | ${project.encoding}
15 |
16 | 17
17 | 3.1.1
18 | 1.18.28
19 | 42.2.8
20 |
21 |
22 |
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 | ${spring.boot.version}
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-data-rest
33 | ${spring.boot.version}
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-data-jpa
38 | ${spring.boot.version}
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-test
43 | ${spring.boot.version}
44 | test
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-security
49 | ${spring.boot.version}
50 |
51 |
52 |
53 | org.postgresql
54 | postgresql
55 | ${postgreSQL.version}
56 | runtime
57 |
58 |
59 |
60 | javax.inject
61 | javax.inject
62 | 1
63 |
64 |
65 | org.projectlombok
66 | lombok
67 | ${lombok.version}
68 | provided
69 |
70 |
71 |
72 |
73 |
74 |
75 | org.apache.maven.plugins
76 | maven-compiler-plugin
77 |
78 |
79 | ${java.version}
80 | ${java.version}
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/src/main/java/com/kaluzny/Application.java:
--------------------------------------------------------------------------------
1 | package com.kaluzny;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(Application.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/kaluzny/domain/Book.java:
--------------------------------------------------------------------------------
1 | package com.kaluzny.domain;
2 |
3 | import jakarta.persistence.*;
4 | import lombok.*;
5 |
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | @Entity
11 | @Getter
12 | @Setter
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @EqualsAndHashCode
16 | @ToString
17 | public class Book {
18 |
19 | @Id
20 | @GeneratedValue(strategy = GenerationType.SEQUENCE)
21 | private Long id;
22 |
23 | private String name;
24 |
25 | private String description;
26 |
27 | @ElementCollection(fetch = FetchType.EAGER)
28 | @CollectionTable(name = "tag")
29 | @Column(name = "Value")
30 | private List tags = new ArrayList<>();
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/kaluzny/domain/BookRepository.java:
--------------------------------------------------------------------------------
1 | package com.kaluzny.domain;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 | import org.springframework.data.rest.core.annotation.RepositoryRestResource;
5 |
6 | import java.util.List;
7 |
8 | @RepositoryRestResource
9 | public interface BookRepository extends JpaRepository {
10 | List findByName(String name);
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/kaluzny/web/BookRestController.java:
--------------------------------------------------------------------------------
1 | package com.kaluzny.web;
2 |
3 | import com.kaluzny.domain.Book;
4 | import com.kaluzny.domain.BookRepository;
5 | import jakarta.persistence.EntityNotFoundException;
6 | import lombok.RequiredArgsConstructor;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.MediaType;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 |
13 | import java.util.Collection;
14 |
15 | @RestController
16 | @RequestMapping(value = "/api", produces = MediaType.APPLICATION_JSON_VALUE)
17 | @RequiredArgsConstructor
18 | @Slf4j
19 | public class BookRestController {
20 |
21 | private final BookRepository repository;
22 |
23 | @PostMapping("/books")
24 | @ResponseStatus(HttpStatus.CREATED)
25 | public Book saveBook(@RequestBody Book book) {
26 | log.info("saveBook() - start: book = {}", book);
27 | Book savedBook = repository.save(book);
28 | log.info("saveBook() - end: savedBook = {}", savedBook.getId());
29 | return savedBook;
30 | }
31 |
32 | @GetMapping("/books")
33 | @ResponseStatus(HttpStatus.OK)
34 | public Collection getAllBooks() {
35 | log.info("getAllBooks() - start");
36 | Collection collection = repository.findAll();
37 | log.info("getAllBooks() - end");
38 | return collection;
39 | }
40 |
41 | @GetMapping("/books/{id}")
42 | @ResponseStatus(HttpStatus.OK)
43 | public Book getBookById(@PathVariable Long id) {
44 | log.info("getBookById() - start: id = {}", id);
45 | Book receivedBook = repository.findById(id)
46 | .orElseThrow(() -> new EntityNotFoundException("Entity with id = Not found"));
47 | log.info("getBookById() - end: book = {}", receivedBook.getId());
48 | return receivedBook;
49 | }
50 |
51 | @GetMapping(value = "/books", params = {"name"})
52 | @ResponseStatus(HttpStatus.OK)
53 | public Collection findBookByName(@RequestParam(value = "name") String name) {
54 | log.info("findBookByName() - start: name = {}", name);
55 | Collection collection = repository.findByName(name);
56 | log.info("findBookByName() - end: collection = {}", collection);
57 | return collection;
58 | }
59 |
60 | @PutMapping("/books/{id}")
61 | @ResponseStatus(HttpStatus.OK)
62 | public Book refreshBook(@PathVariable("id") long id, @RequestBody Book book) {
63 | log.info("refreshBook() - start: id = {}, book = {}", id, book);
64 | Book updatedBook = repository.findById(id)
65 | .map(entity -> {
66 | entity.setName(book.getName());
67 | entity.setDescription(book.getDescription());
68 | entity.setTags(book.getTags());
69 | return repository.save(entity);
70 | })
71 | .orElseThrow(() -> new EntityNotFoundException("Book with id = Not found"));
72 | log.info("refreshBook() - end: updatedBook = {}", updatedBook);
73 | return updatedBook;
74 | }
75 |
76 | @DeleteMapping("/books/{id}")
77 | @ResponseStatus(HttpStatus.NO_CONTENT)
78 | public void removeBookById(@PathVariable Long id) {
79 | log.info("removeBookById() - start: id = {}", id);
80 | repository.deleteById(id);
81 | log.info("removeBookById() - end: id = {}", id);
82 | }
83 |
84 | @DeleteMapping("/books")
85 | @ResponseStatus(HttpStatus.NO_CONTENT)
86 | public void removeAllBooks() {
87 | log.info("removeAllBooks() - start");
88 | repository.deleteAll();
89 | log.info("removeAllBooks() - end");
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/resources/Request.http:
--------------------------------------------------------------------------------
1 | # For a quick start check out our HTTP Requests collection (Tools|HTTP Client|Open HTTP Requests Collection) or
2 | # paste cURL into the file and request will be converted to HTTP Request format.
3 | #
4 | # Following HTTP Request Live Templates are available:
5 | # * 'gtrp' and 'gtr' create a GET request with or without query parameters;
6 | # * 'ptr' and 'ptrp' create a POST request with a simple or parameter-like body;
7 | # * 'mptr' and 'fptr' create a POST request to submit a form with a text or file field (multipart/form-data);
8 |
9 | ### Send POST request with json body
10 | POST http://localhost:8080/api/books
11 | Accept: application/json
12 | Authorization: Basic dXNlcjp1c2Vy
13 | Content-Type: application/json
14 |
15 | {
16 | "name": "Java",
17 | "description": "Programming",
18 | "tags": [
19 | "#lambdaexpressions, #streams, #functionalprogramming"
20 | ]
21 | }
22 |
23 | ###
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | # Spring Boot configuration
2 | spring:
3 | profiles:
4 | active: development
5 | # Security configuration
6 | security:
7 | user:
8 | name: user
9 | password: user
10 | # Database
11 | datasource:
12 | driver-class-name: org.postgresql.Driver
13 | url: jdbc:postgresql://localhost:5432/book_db
14 | username: postgres
15 | password: postgres
16 | # JPA properties
17 | jpa:
18 | hibernate:
19 | ddl-auto: update # When you launch the application for the first time - switch "none" at "create"
20 | show-sql: true
21 | database: postgresql
22 | database-platform: org.hibernate.dialect.PostgreSQLDialect
23 | open-in-view: false
24 | generate-ddl: true
25 | # Logger configuration
26 | logging:
27 | pattern:
28 | console: "%d %-5level %logger : %msg%n"
29 | level:
30 | org.springframework: info
31 | org.hibernate: debug
32 | # Server configuration
33 | server:
34 | port: 8080 #set your port
35 |
--------------------------------------------------------------------------------
/src/main/resources/body.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Java",
3 | "description": "Programming",
4 | "tags": [
5 | "#lambdaexpressions, #streams, #functionalprogramming"
6 | ]
7 | }
--------------------------------------------------------------------------------
/travis-ci.bat:
--------------------------------------------------------------------------------
1 | mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
2 |
--------------------------------------------------------------------------------