Home Spring POST Lesson
Post
Cancel

Spring POST Lesson

UML Backend Diagram

Link to IMG: https://ibb.co/dmJMqJD

SPRING POST

Comprehensive Guide to RESTful API Methods and HTTP Status Codes for Users

RESTful API Methods for Users

1. GET: /users

  • Description: Retrieve a list of users from the system.
  • Example Request: GET /users
  • Example Response: A successful response with a status code of 200 OK will include a JSON array containing details of multiple users.

2. GET: /users(id)

  • Description: Fetch a single user by their unique identifier (ID).
  • Example Request: GET /users/123 –> This is the ID
  • Example Response: A successful response (status code 200 OK) will contain a JSON object representing the user with ID 123.

3. POST: /users

  • Description: Create a new user in the system.
  • Example Request: To add a new user, send a POST request to /users with a JSON payload containing the necessary user information.
  • Example Response: A successful response (status code 200 OK) will include a JSON object representing the newly created user.

4. PUT: /users(id)

  • Description: Update an existing user identified by their ID.
  • Example Request: To modify user details, send a PUT request to /users/123 with a JSON payload containing the updated information.
  • Example Response: A successful response (status code 200 OK) will include a JSON object representing the user with updated details.

5. DELETE: /users(id)

  • Description: Remove a user from the system based on their ID.
  • Example Request: To delete a user, send a DELETE request to /users/123.
  • Example Response: A successful response (status code 200 OK) may include a message confirming the deletion.

HTTP Status Codes

1. 200 OK

  • Description: The request was successful, and the server returns the requested data.
  • Example Usage: After a successful GET, POST, PUT, or DELETE operation, the server responds with a 200 OK status code.

2. 400 Bad Request

  • Description: The server cannot understand the request, often due to malformed syntax or missing parameters.
  • Example Usage: If the request is incorrectly formatted or lacks required information, the server responds with a 400 Bad Request status code.

3. 404 Not Found

  • Description: The requested resource (user) could not be found on the server.
  • Example Usage: When attempting to GET, PUT, or DELETE a user who does not exist, the server responds with a 404 Not Found status code.

4. 500 Internal Server Error

  • Description: A generic error message indicating that an unexpected condition was encountered on the server.
  • Example Usage: If the server encounters an unexpected issue, such as a bug or unhandled exception, it responds with a 500 Internal Server Error status code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@Controller
@RequestMapping("/mvc/person")
public class PersonViewController {
    // Autowired enables Control to connect HTML and POJO Object to database easily for CRUD
    @Autowired
    private PersonDetailsService repository;

    @GetMapping("/read")
    public String person(Model model) {
        List<Person> list = repository.listAll();
        model.addAttribute("list", list);
        return "person/read";
    }

    /*  The HTML template Forms and PersonForm attributes are bound
        @return - template for person form
        @param - Person Class
    */
    @GetMapping("/create")
    public String personAdd(Person person) {
        return "person/create";
    }

    /* Gathers the attributes filled out in the form, tests for and retrieves validation error
    @param - Person object with @Valid
    @param - BindingResult object
     */
    @PostMapping("/create")
    public String personSave(@Valid Person person, BindingResult bindingResult) {
        // Validation of Decorated PersonForm attributes
        if (bindingResult.hasErrors()) {
            return "person/create";
        }
        repository.save(person);
        repository.addRoleToPerson(person.getEmail(), "ROLE_STUDENT");
        // Redirect to next step
        return "redirect:/mvc/person/read";
    }

    @GetMapping("/update/{id}")
    public String personUpdate(@PathVariable("id") int id, Model model) {
        model.addAttribute("person", repository.get(id));
        return "person/update";
    }

    @PostMapping("/update")
    public String personUpdateSave(@Valid Person person, BindingResult bindingResult) {
        // Validation of Decorated PersonForm attributes
        if (bindingResult.hasErrors()) {
            return "person/update";
        }
        repository.save(person);
        repository.addRoleToPerson(person.getEmail(), "ROLE_STUDENT");

        // Redirect to next step
        return "redirect:/mvc/person/read";
    }

    @GetMapping("/delete/{id}")
    public String personDelete(@PathVariable("id") long id) {
        repository.delete(id);
        return "redirect:/mvc/person/read";
    }

    @GetMapping("/search")
    public String person() {
        return "person/search";
    }

}

Introduction to Databases and JSONB

Databases and Complex Data Storage

  • Overview of Databases:
    • Databases are essential in storing, retrieving, and managing data.
    • They support a range of data types and structures, from simple to complex.
  • Need for Storing Complex Data:
    • Modern applications often require the storage of nested, non-uniform data.
    • Traditional database structures can be limiting when dealing with dynamic or hierarchical data.

Understanding JSONB

Definition and Characteristics of JSONB

  • What is JSONB?
    • JSONB stands for JSON Binary.
    • It is a specialized data format used in PostgreSQL and other SQL databases to store JSON (JavaScript Object Notation) documents in a binary, efficient form.
  • Key Characteristics:
    • Binary Format: Unlike standard JSON, JSONB is stored in a decomposed binary format.
    • Indexing: Allows for the creation of GIN (Generalized Inverted Index) indexes, enhancing search capabilities.

Comparison with Traditional JSON

  • Performance:
    • JSONB offers faster processing (e.g., search, retrieval) as it avoids reparsing the data, unlike textual JSON storage.
  • Flexibility:
    • While JSONB consumes slightly more disk space, it provides significantly more flexibility in querying and manipulating data.
  • Use Cases for JSONB:
    • Ideal for storing dynamic or unstructured data.
    • Beneficial when frequent read and write operations are performed on the JSON data.

Storing HashMaps with JSONB

Practical Example: Storing User Stats as a Nested JSONB Structure

  • Scenario: Storing diverse user statistics where the structure can vary for each user.

Java Code Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.util.HashMap;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Column;
import javax.persistence.Convert;
import org.hibernate.annotations.Type;

@Entity
public class UserStats {

    @Id
    private Long id;

    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    private Map<String, Map<String, Object>> stats = new HashMap<>();

    // Standard getters and setters
}

# Integration with Java Backend

## POJO and Database Interaction

- **What is a POJO?**
  - POJO stands for Plain Old Java Object.
  - It's a Java object not bound by any restriction other than those forced by the Java Language Specification.

- **Role in Database Interaction**:
  - POJOs are used to encapsulate data and represent database entities in object-oriented programming.
  - They interact with databases through Object-Relational Mapping (ORM) frameworks like Hibernate.

#### Defining a POJO with JSONB Field

```java
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Column;
import javax.persistence.Convert;
import java.util.Map;
import java.util.HashMap;
import org.hibernate.annotations.Type;

@Entity
public class User {

    @Id
    private Long id;

    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    private Map<String, Map<String, Object>> additionalProperties = new HashMap<>();

    // Standard getters and setters

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Map<String, Map<String, Object>> getAdditionalProperties() {
        return additionalProperties;
    }

    public void setAdditionalProperties(Map<String, Map<String, Object>> additionalProperties) {
        this.additionalProperties = additionalProperties;
    }
}

Introduction to JPA

  • What is JPA?
    • JPA stands for Java Persistence API.
    • It’s a specification for accessing, persisting, and managing data between Java objects and a relational database.
  • JPA in Database Operations:
    • JPA allows developers to define database tables with Java classes.
    • Provides a set of annotations to map Java objects to database tables.

Using JPA Repository

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByLastName(String lastName);
    Optional<User> findByEmail(String email);
    List<User> findByAgeGreaterThan(int age);
}

CRUD Operations with JSONB

Detailed Guide on CRUD Operations

  • Create, Read, Update, Delete (CRUD):
    • These are the four basic functions of persistent storage in applications.
    • JSONB fields can be integrated into CRUD operations for enhanced data handling.

Java Code Examples for CRUD Operations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

public class UserStatsService {

    @PersistenceContext
    private EntityManager entityManager;

    // Create
    @Transactional
    public void createUserStat(UserStats userStat) {
        entityManager.persist(userStat);
    }

    // Read
    public UserStats getUserStat(Long id) {
        return entityManager.find(UserStats.class, id);
    }

    // Update
    @Transactional
    public void updateUserStat(Long id, Map<String, Map<String, Object>> newStats) {
        UserStats userStat = getUserStat(id);
        if (userStat != null) {
            userStat.setStats(newStats);
            entityManager.merge(userStat);
        }
    }

    // Delete
    @Transactional
    public void deleteUserStat(Long id) {
        UserStats userStat = getUserStat(id);
        if (userStat != null) {
            entityManager.remove(userStat);
        }
    }
}


# Example Code with all Rest API Methods


```java
// User model class representing the user entity
public class User {
    private Long id;
    private String username;
    private String email;
    // other fields, getters, setters
}

// UserController class handling user-related API requests
@RestController //handles HTTP requests and produces JSON responses.
@RequestMapping("/users")
public class UserController {

    // Service for handling user-related operations
    @Autowired
    private UserService userService;

    // GET: Retrieve a list of users (read)
    @GetMapping
    public ResponseEntity<List<User>> getUsers() {
        List<User> users = userService.getAllUsers();
        return new ResponseEntity<>(users, HttpStatus.OK);
    }

    // GET: Fetch a single user by ID (read)
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.getUserById(id);
        return new ResponseEntity<>(user, HttpStatus.OK);
    }

    // POST: Create a new user (Create)
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User newUser) {
        User createdUser = userService.createUser(newUser);
        return new ResponseEntity<>(createdUser, HttpStatus.CREATED);
    }

    // PUT: Update an existing user by ID (Update)
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User updatedUser) {
        User user = userService.updateUser(id, updatedUser);
        return new ResponseEntity<>(user, HttpStatus.OK);
    }

    // DELETE: Remove a user by ID (Delete)
    @DeleteMapping("/{id}")
    public ResponseEntity<String> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return new ResponseEntity<>("User deleted successfully", HttpStatus.OK);
    }
}

// UserService interface defining user-related operations
public interface UserService { //declares all 5 methods of CRUD
    List<User> getAllUsers();
    User getUserById(Long id);
    User createUser(User user);
    User updateUser(Long id, User updatedUser);
    void deleteUser(Long id);
}

User Class (Model):

  • Represents the user entity with fields such as id, username, and email.
  • Follows the standard Java Bean conventions with private fields and public getters and setters.

UserController Class (Controller):

  • Handles API requests related to users.
  • Annotated with @RestController to indicate that it handles HTTP requests and produces JSON responses.
  • Defines various endpoints (/users, /users/{id}) for CRUD (Create, Read, Update, Delete) operations on users.
  • Utilizes UserService for handling business logic.

UserServiceImpl Class (Service):

  • Implements the UserService interface.
  • Maintains an in-memory list of users.
  • Implements methods to perform operations like getting all users, getting a user by ID, creating, updating, and deleting users.

Endpoints:

  • GET /users: Retrieves a list of all users.
  • GET /users/{id}: Fetches a single user by ID.
  • POST /users: Creates a new user. = PUT /users/{id}: Updates an existing user by ID. = DELETE /users/{id}: Deletes a user by ID.

HTTP Responses:

  • Responses are wrapped in ResponseEntity objects with appropriate HTTP status codes.
  • For example, successful creation returns 201 Created, successful update returns 200 OK, and successful deletion returns 200 OK.
This post is licensed under CC BY 4.0 by the author.

Login Lesson

Spring Roles for User/Admin