RESTful API [JAVA/SPRING] --> ReactJS (Client) --> DB
PART 1: API SERVER [SPRING]
Step 1: Defining API Endpoints --> Map Each Method with HTTP Verbs
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users")
public String getAllUsers() {
// Logic to retrieve all users from the database
return "List of all users";
}
@GetMapping("/users/{id}")
public String getUserById(@PathVariable int id) {
// Logic to retrieve a user by ID from the database
return "User with ID: " + id;
}
// ------------------------------- IMPLEMENTATION ------------------------------------
@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(@PathVariable int id) {
User user = userService.getUserById(id);
if (user != null) {
return new ResponseEntity<>(user, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@PostMapping("/users")
public String createUser(@RequestBody User user) {
// Logic to create a new user in the database
return "User created: " + user.getName();
}
@PutMapping("/users/{id}")
public String updateUser(@PathVariable int id, @RequestBody User user) {
// Logic to update a user with the given ID in the database
return "User updated: " + user.getName();
}
@DeleteMapping("/users/{id}")
public String deleteUser(@PathVariable int id) {
// Logic to delete a user with the given ID from the database
return "User deleted with ID: " + id;
}
}
Explanation:
- We define a `UserController` class as a REST controller using the `@RestController` annotation.
- The base URL for all endpoints in this controller is `/api`.
- We define various endpoints using annotations like `@GetMapping`, `@PostMapping`,
specifying the URL paths for each endpoint and mapping each method to URL endpoints.
- The methods inside the controller handle HTTP requests and responses.
---------------------------------------------------------------------------------------------------------------------------------
In the implementation example, the API responses are generated using the ResponseEntity class from Spring Framework.
- The ResponseEntity allows you to set the response body, HTTP status code, and other HTTP headers.
- In the getAllUsers method, the list of users is retrieved from the userService, and then a ResponseEntity is created with the users list and HttpStatus.OK (200) status code.
- In the getUserById method, a single user is retrieved from the userService based on the provided ID. If the user is found, a ResponseEntity with the user object and HttpStatus.OK (200) status code is returned. If the user is not found, a ResponseEntity with HttpStatus.NOT_FOUND (404) status code is returned.
Step 2: Define HTTP Methods
In the previous step, we used annotations such as `@GetMapping`, `@PostMapping`,
`@PutMapping`, and `@DeleteMapping` to specify the HTTP methods for each endpoint.
Step 3: Handling RESTful API Request/Response
This is done through the method implementations inside the `UserController` class.
For example, `getAllUsers` returns a list of all users, `getUserById` returns a specific user by ID,
`createUser` creates a new user, `updateUser` updates an existing user, and `deleteUser` deletes a user.
Step 4: Server-side Logic for Handling Data
To handle the data, you would typically have a service class and a data repository class. Here's an example:
```java
@Service
public class UserService {
public List<User> getAllUsers() {
// Logic to retrieve all users from the database using UserRepository
// ...
}
public User getUserById(int id) {
// Logic to retrieve a user by ID from the database using UserRepository
// ...
}
public void createUser(User user) {
// Logic to create a new user in the database using UserRepository
// ...
}
public void updateUser(int id, User user) {
// Logic to update a user with the given ID in the database using UserRepository
// ...
}
public void deleteUser(int id) {
// Logic to delete a user with the given ID from the database using UserRepository
// ...
}
}
@Repository
public class UserRepository {
public List<User> getAllUsers() {
// Logic to retrieve all users from the database
// ...
}
// Other Methods ............................
}
Explanation:
- The `UserService` class contains methods for handling user related business logic.
It interacts with the `UserRepository` class to perform CRUD operations on the database.
- The `UserRepository` class is responsible for data access operations
such as retrieving, creating, updating, and deleting users from the database.
Step 5: Consuming API via Client
To consume the API, you can use HTTP clients like `RestTemplate` or `HttpClient`
in your Java application. Here's an example using `RestTemplate`:
```java
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class ApiConsumer {
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
// GET request to retrieve all users
ResponseEntity<String> response = restTemplate.exchange(
"http://localhost:8080/api/users",
HttpMethod.GET,
null,
String.class);
System.out.println("Response: " + response.getBody());
// Other HTTP requests (POST, PUT, DELETE) can be similarly performed using RestTemplate
}
}
```
Explanation:
- We create an instance of `RestTemplate`.
- We use `exchange` method to send a GET request to
the specified URL (`http://localhost:8080/api/users`) and retrieve the response.
- The retrieved response can be processed and used as per your application's requirements.
PART 2: REACT.js CLIENT UI
Let's go through the details of how and where the API data exchange
occurs in both the Java app (API server) and the React app (API client).
Java Spring MVC (API Server):
1. Defining API Endpoints:
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable int id) {
// Implementation to fetch and return user by ID
}
@PostMapping
public void createUser(@RequestBody User user) {
// Implementation to create a new user
}
@PutMapping("/{id}")
public void updateUser(@PathVariable int id, @RequestBody User user) {
// Implementation to update an existing user
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable int id) {
// Implementation to delete a user by ID
}
}
- In the example above, the @RequestMapping annotation is used at the class level
to define the base URL path for all the endpoints defined within the UserController class.
-The @GetMapping, @PostMapping, @PutMapping, and @DeleteMapping
annotations are used at the method level to map specific HTTP methods to corresponding actions.
2A [DB]. Handling RESTful API Request/Response in Backend DB:
The Java app handles the RESTful API request and response within the endpoint methods.
For example, in the `getAllUsers` method, you would
write the logic to retrieve all users from the database and return the response. Here's an example
```java
@GetMapping("/users")
public List<User> getAllUsers() {
List<User> users = userService.getAllUsers(); // Logic to retrieve users from the service
return users;
}
```
2B [Server-Side API Client] Server side Logic for Handling Data:
To handle the data, you typically have service and repository classes.
The service class contains methods that interact with the repository to perform CRUD operations.
The repository class handles the data access operations. Here's an example:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class APIClient {
private static final String BASE_URL = "http://your-api-domain.com/api/users";
public static void main(String[] args) {
try {
// GET request to fetch a user by ID
getUser(1);
// POST request to create a new user
createUser();
// PUT request to update an existing user
updateUser(1);
// DELETE request to delete a user by ID
deleteUser(1);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void getUser(int id) throws IOException {
URL url = new URL(BASE_URL + "/" + id);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
System.out.println("GET Request Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
System.out.println("GET Response: " + response.toString());
} else {
System.out.println("GET Request Failed");
}
}
private static void createUser() throws IOException {
URL url = new URL(BASE_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
String requestBody = "{\"name\": \"John Doe\", \"email\": \"john.doe@example.com\"}";
OutputStream outputStream = connection.getOutputStream();
outputStream.write(requestBody.getBytes());
outputStream.flush();
outputStream.close();
int responseCode = connection.getResponseCode();
System.out.println("POST Request Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
System.out.println("POST Request Successful");
} else {
System.out.println("POST Request Failed");
}
}
React App (API Client):
1. Making API Requests:
In the React app, you make API requests using an HTTP client library like `axios` of 'fetch' instead of 2A, 2B
import React, { useEffect, useState } from 'react';
function UserComponent() {
const [user, setUser] = useState(null);
useEffect(() => {
// GET request to fetch a user by ID
fetch('/api/users/1')
.then(response => response.json())
.then(data => setUser(data))
.catch(error => console.error(error));
}, []);
const createUser = () => {
// POST request to create a new user
fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John Doe', email: 'john.doe@example.com' })
})
.then(response => {
if (response.ok) {
console.log('POST Request Successful');
// Perform additional actions or update state if needed
} else {
console.log('POST Request Failed');
}
})
.catch(error => console.error(error));
};
const updateUser = () => {
// PUT request to update an existing user
fetch('/api/users/1', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'Updated User', email: 'updated.user@example.com' })
})
.then(response => {
if (response.ok) {
console.log('PUT Request Successful');
// Perform additional actions or update state if needed
} else {
console.log('PUT Request Failed');
}
})
.catch(error => console.error(error));
};
const deleteUser = () => {
// DELETE request to delete a user by ID
fetch('/api/users/1', { method: 'DELETE' })
.then(response => {
if (response.ok) {
console.log('DELETE Request Successful');
// Perform additional actions or update state if needed
} else {
console.log('DELETE Request Failed');
}
})
.catch(error => console.error(error));
};
return (
<div>
{user ? (
<div>
<h2>User Details:</h2>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
</div>
) : (
<p>Loading user...</p>
)}
<button onClick={createUser}>Create User</button>
<button onClick={updateUser}>Update User</button>
<button onClick={deleteUser}>Delete User</button>
</div>
);
}
export default UserComponent;
2. Consuming API Responses:
Once the API response is received, you can consume the data within your React components.
EX) in the `UserList` component, you map over the `users` array and
render each user's name as a list item. Here's an example:
const UserList = () => {
// ...
return (
<div>
<h2>User List</h2>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
No, you won't need the Java code snippet that uses HttpURLConnection in your React application.
The Java code was provided as an alternative example for making API requests in Java.
In your React application, you can use the provided React code snippet
to make API requests using the fetch function.
The React code uses JavaScript and is specifically tailored to work within a React component.
The Java code snippet using HttpURLConnection is unrelated to the React code and
can be disregarded unless you plan to make API requests in a Java environment outside of your React application.
Q: User so I just need java usercontroller class and the react code snippet you provided?
Yes, that's correct. You need the Java UserController class (which contains the API endpoint mappings) and
the React code snippet to make API requests from your React application.
The Java UserController class is responsible for handling the API endpoints
and their corresponding actions on the server-side.
It receives HTTP requests from the client (such as the React application) and performs the necessary operations.
On the other hand, the React code snippet is responsible for making HTTP requests
from the client-side (the React application). It uses the fetch function to send requests
to the API endpoints defined in the UserController and handles the responses.
By combining the Java UserController class on the server-side and the
React code snippet on the client-side, you can establish communication
between the React application and the server API, allowing you to perform CRUD
PART 3: BACKEND RDBMS (MySQL)
To integrate a backend database into the example we discussed earlier,
we'll need to modify the Java app (API server) to interact with the database.
Here's an updated version of the code snippets with the
addition of a database integration using JPA (Java Persistence API) and Hibernate.
Step 1: Set Up the Database
Assuming you're using a relational database such as MySQL,
you'll need to set up the database and configure the connection details in your Java app.
Step 2: Create a User Entity
In your Java app, create an entity class to represent the
User model and map it to the database table. Here's an example:
```java
import javax.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
// Getters and setters
}
```
Explanation:
- The `User` class is annotated with `@Entity` to specify that it is an entity mapped to a database table.
- The `@Table` annotation specifies the name of the database table.
- The `@Id` annotation denotes the primary key field.
- The `@GeneratedValue` annotation specifies the generation strategy for the primary key.
Step 3: Create a UserRepository
Create a repository interface that extends the `JpaRepository` interface provided by Spring Data JPA.
This interface will provide CRUD operations for the `User` entity. Here's an example:
```java
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
```
Explanation:
- The `UserRepository` interface extends `JpaRepository<User, Long>`, where `User` is the entity type
and `Long` is the type of the primary key field.
Step 4: Modify the UserService
Update the `UserService` class to use the `UserRepository` for data access operations. Here's an example:
```java
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
private UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
public User createUser(User user) {
return userRepository.save(user);
}
// Other methods for updating and deleting users
}
```
Explanation:
- The `UserService` class now uses the `UserRepository` for CRUD operations on the database.
- The `userRepository.save(user)` method is used to save a new user to the database.
Step 5: Update the UserController
Modify the `UserController` class to use the `UserService` for handling data operations. Here's an example:
```java
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
public class UserController {
private UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/users")
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
// Other methods for updating and deleting users
}
```
Explanation:
- The `UserController` class now uses the `UserService` for handling data operations.
- The `@RequestBody` annotation is used to deserialize the JSON request body into a `User` object.
With these modifications, the Java app (API server) is now integrated with the database.
The API server interacts with the database through the JPA and Hibernate integration,
providing CRUD operations for the `User` entity.
The React app (API client) remains the same and can consume the API
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
SAMPLE
import java.util.Scanner;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
// Rest of the code...
private static void registerUser(Scanner scanner, Bank bank) {
// Rest of the code...
// Create the request body JSON
String requestBody = "{\"name\": \"" + name + "\", \"address\": \"" + address + "\", \"phoneNumber\": \"" + phoneNumber + "\", \"age\": " + age + ", \"dateOfBirth\": \"" + dateOfBirth + "\", \"pin\": " + pin + "}";
// Define the API endpoint URL
String url = "http://localhost:8080/users";
// Create an HttpClient instance
HttpClient httpClient = HttpClient.newHttpClient();
// Create the HTTP request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
try {
// Send the HTTP request and retrieve the response
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// Process the response
int statusCode = response.statusCode();
String responseBody = response.body();
// Rest of the code...
} catch (Exception e) {
System.out.println("An error occurred during the API request: " + e.getMessage());
}
// Rest of the code...
}
private static void atmPage(Scanner scanner, Bank bank) {
// Rest of the code...
// Create the request URL to get the card
String url = "http://localhost:8080/cards/" + enteredCardNo;
// Create an HttpClient instance
HttpClient httpClient = HttpClient.newHttpClient();
// Create the HTTP request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.GET()
.build();
try {
// Send the HTTP request and retrieve the response
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// Process the response
int statusCode = response.statusCode();
String responseBody = response.body();
// Rest of the code...
} catch (Exception e) {
System.out.println("An error occurred during the API request: " + e.getMessage());
}
// Rest of the code...
}
private static void atmOperations(Scanner scanner, Bank bank, Card card) {
// Rest of the code...
// Create the request URL to get the account
String url = "http://localhost:8080/accounts/" + card.getAccountId();
// Create an HttpClient instance
HttpClient httpClient = HttpClient.newHttpClient();
// Create the HTTP request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.GET()
.build();
try {
// Send the HTTP request and retrieve the response
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// Process the response
int statusCode = response.statusCode();
String responseBody = response.body();
// Rest of the code...
} catch (Exception e) {
System.out.println("An error occurred during the API request: " + e.getMessage());
}
// Rest of the code...
}
// Rest of the code...
}