diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 08280bb..4c940f3 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -37,7 +37,7 @@ "state": { "type": "markdown", "state": { - "file": "Home.md", + "file": "Post.md", "mode": "source", "source": false } @@ -122,7 +122,7 @@ "state": { "type": "backlink", "state": { - "file": "Home.md", + "file": "Post.md", "collapseAll": false, "extraContext": false, "sortOrder": "alphabetical", @@ -139,7 +139,7 @@ "state": { "type": "outgoing-link", "state": { - "file": "Home.md", + "file": "Post.md", "linksCollapsed": false, "unlinkedCollapsed": true } @@ -162,7 +162,7 @@ "state": { "type": "outline", "state": { - "file": "Home.md" + "file": "Post.md" } } } @@ -185,9 +185,9 @@ }, "active": "92c92033d31ed01c", "lastOpenFiles": [ + "Home.md", "Post.md", "GET.md", - "Home.md", "Get.md", "assets/Pasted image 20230721100304.png", "Database.md", diff --git a/Home.md b/Home.md index 7e2a8a4..8e684a1 100644 --- a/Home.md +++ b/Home.md @@ -1,4 +1,4 @@ -This repo is my first attempt to learn `SpringBoot` following [this](https://spring.academy/courses/building-a-rest-api-with-spring-boot/lessons/introduction) tutorial. The setup is Visual Code IDE alongside with [SpringBoot](https://code.visualstudio.com/docs/java/java-spring-boot) plugin. +This repo is my first attempt to learn `SpringBoot` following [this](https://spring.academy/courses/building-a-rest-api-with-spring-boot/lessons/introduction) tutorial. The setup is Visual Code IDE alongside with [SpringBoot](https://code.visualstudio.com/docs/java/java-spring-boot) plugin. It is advised to use [Obsidian](https://obsidian.md/) to read this wiki. # Spring Initializr @@ -76,7 +76,7 @@ public class CashCardController { That’s all it takes to tell Spring: “create a REST Controller”. The Controller gets injected into Spring Web, which routes API requests (handled by the Controller) with help of [[Get#@GetMapping]] annotation to the correct method. ## Get -**** + In [[Get]] requests, the body is empty. So, the request to read the Cash Card with an id of 123 would be: ``` @@ -124,9 +124,13 @@ This leaves us with the `POST` and `PATCH` options. As it turns out, REST permit ### The [[Post]] Request -The `POST` method allows a Body, so we will use the Body to send a JSON representation of the object: +We want our Cash Card API to behave as semantically correctly as possible. Meaning, users of our API should not be surprised by how it behaves. We'll begin by writing a failing test of what we expect success to look like. -Request: +Let's refer to the official Request for Comments for HTTP Semantics and Content ([RFC 7231](https://www.rfc-editor.org/rfc/rfc7231)) for guidance as to how our API should behave. For our `POST` endpoint, review this section about [HTTP POST](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3); note that we have added emphasis: + +> If one or more resources has been created on the origin server as a result of successfully processing a POST request, **_the origin server SHOULD send a 201 (Created) response containing a Location header field that provides an identifier for the primary resource created ..._** + +The `POST` method allows a Body, so we will use the Body to send a JSON representation of the object in the Request: - Method: `POST` - URI: `/cashcards/` @@ -173,7 +177,7 @@ return ResponseEntity .build(); ``` -Aren’t you glad Spring Web provides the `.created()` convenience method? +Aren’t you glad Spring Web provides the `.created()` convenience method? Check the complete [[Post]] implementation. # Database diff --git a/Post.md b/Post.md index ec6d3de..f242ef6 100644 --- a/Post.md +++ b/Post.md @@ -1,10 +1,4 @@ -# Test the HTTP POST Endpoint - -We want our Cash Card API to behave as semantically correctly as possible. Meaning, users of our API should not be surprised by how it behaves. We'll begin by writing a failing test of what we expect success to look like. - -Let's refer to the official Request for Comments for HTTP Semantics and Content ([RFC 7231](https://www.rfc-editor.org/rfc/rfc7231)) for guidance as to how our API should behave. For our `POST` endpoint, review this section about [HTTP POST](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3); note that we have added emphasis: - -> If one or more resources has been created on the origin server as a result of successfully processing a POST request, **_the origin server SHOULD send a 201 (Created) response containing a Location header field that provides an identifier for the primary resource created ..._** +# Test the HTTP Post Endpoint Edit `src/test/java/example/cashcard/CashCardApplicationTests.java` and add the following test method. @@ -52,9 +46,7 @@ URI locationOfNewCashCard = createResponse.getHeaders().getLocation(); Note that URI is indeed the correct entity here and _not_ a URL; a [URL is a type of URI](https://www.w3.org/TR/uri-clarification/#contemporary), while a URI is more generic. -# The POST - -## Simple endpoint stub +# Simple endpoint stub The `POST` endpoint is similar to the `GET` endpoint in our `CashCardController`, but uses the `@PostMapping` annotation from Spring Web. The `POST` endpoint must accept the data we are submitting for our new `CashCard`, specifically the `amount`. But what happens if we don't accept the `CashCard`? @@ -72,7 +64,7 @@ private ResponseEntity createCashCard() { Note that by returning nothing at all, Spring Web will automatically generate an HTTP Response Status code of `200 OK`. But, this isn't very satisfying -- our `POST` endpoint does nothing! So let's make our tests better. -## Actual implementation +# Actual implementation ```java import org.springframework.web.util.UriComponentsBuilder; @@ -92,7 +84,7 @@ private ResponseEntity createCashCard(@RequestBody CashCard newCashCardReq } ``` -### CrudRepository.save +## CrudRepository.save ```java CashCard savedCashCard = cashCardRepository.save(newCashCardRequest); @@ -100,7 +92,7 @@ CashCard savedCashCard = cashCardRepository.save(newCashCardRequest); `CrudRepository` provides methods that support creating, reading, updating, and deleting data from a data store. `cashCardRepository.save(newCashCardRequest)` does just as it says: it saves a new `CashCard` for us, and returns the saved object with a unique `id` provided by the database. Amazing! -### Post request, get the body +## Post request, get the body ```java createCashCard(@RequestBody CashCard newCashCardRequest, ...) @@ -108,7 +100,8 @@ createCashCard(@RequestBody CashCard newCashCardRequest, ...) Unlike the `GET` we added earlier, the `POST` expects a request "body". This contains the data submitted to the API. Spring Web will deserialize the data into a `CashCard` for us. -### Location Header +## `Location` Header + ```java URI locationOfNewCashCard = ucb .path("cashcards/{id}")